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 WhileStatement extends Statement { 21 22 public Expression condition; 23 public Statement action; 24 private BranchLabel breakLabel, continueLabel; 25 int preCondInitStateIndex = -1; 26 int condIfTrueInitStateIndex = -1; 27 int mergedInitStateIndex = -1; 28 29 public WhileStatement(Expression condition, Statement action, int s, int e) { 30 31 this.condition = condition; 32 this.action = action; 33 if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatement; 35 sourceStart = s; 36 sourceEnd = e; 37 } 38 39 public FlowInfo analyseCode( 40 BlockScope currentScope, 41 FlowContext flowContext, 42 FlowInfo flowInfo) { 43 44 breakLabel = new BranchLabel(); 45 continueLabel = new BranchLabel(); 46 47 Constant cst = this.condition.constant; 48 boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; 49 boolean isConditionFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 50 51 cst = this.condition.optimizedBooleanConstant(); 52 boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; 53 boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 54 55 preCondInitStateIndex = 56 currentScope.methodScope().recordInitializationStates(flowInfo); 57 LoopingFlowContext condLoopContext; 58 FlowInfo condInfo = flowInfo.nullInfoLessUnconditionalCopy(); 59 condInfo = this.condition.analyseCode( 63 currentScope, 64 (condLoopContext = 65 new LoopingFlowContext(flowContext, flowInfo, this, null, 66 null, currentScope)), 67 condInfo); 68 69 LoopingFlowContext loopingContext; 70 FlowInfo actionInfo; 71 FlowInfo exitBranch; 72 if (action == null 73 || (action.isEmptyBlock() && currentScope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_3)) { 74 condLoopContext.complainOnDeferredFinalChecks(currentScope, 75 condInfo); 76 condLoopContext.complainOnDeferredNullChecks(currentScope, 77 condInfo.unconditionalInits()); 78 if (isConditionTrue) { 79 return FlowInfo.DEAD_END; 80 } else { 81 FlowInfo mergedInfo = flowInfo.copy().addInitializationsFrom(condInfo.initsWhenFalse()); 82 if (isConditionOptimizedTrue){ 83 mergedInfo.setReachMode(FlowInfo.UNREACHABLE); 84 } 85 mergedInitStateIndex = 86 currentScope.methodScope().recordInitializationStates(mergedInfo); 87 return mergedInfo; 88 } 89 } else { 90 loopingContext = 93 new LoopingFlowContext( 94 flowContext, 95 flowInfo, 96 this, 97 breakLabel, 98 continueLabel, 99 currentScope); 100 if (isConditionFalse) { 101 actionInfo = FlowInfo.DEAD_END; 102 } else { 103 actionInfo = condInfo.initsWhenTrue().copy(); 104 if (isConditionOptimizedFalse){ 105 actionInfo.setReachMode(FlowInfo.UNREACHABLE); 106 } 107 } 108 109 condIfTrueInitStateIndex = 111 currentScope.methodScope().recordInitializationStates( 112 condInfo.initsWhenTrue()); 113 114 if (!this.action.complainIfUnreachable(actionInfo, currentScope, false)) { 115 actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo); 116 } 117 118 exitBranch = flowInfo.copy(); 120 122 if ((actionInfo.tagBits & 123 loopingContext.initsOnContinue.tagBits & 124 FlowInfo.UNREACHABLE) != 0) { 125 continueLabel = null; 126 exitBranch.addInitializationsFrom(condInfo.initsWhenFalse()); 127 } else { 128 condLoopContext.complainOnDeferredFinalChecks(currentScope, 129 condInfo); 130 actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits()); 131 condLoopContext.complainOnDeferredNullChecks(currentScope, 132 actionInfo); 133 loopingContext.complainOnDeferredFinalChecks(currentScope, 134 actionInfo); 135 loopingContext.complainOnDeferredNullChecks(currentScope, 136 actionInfo); 137 exitBranch. 138 addPotentialInitializationsFrom( 139 actionInfo.unconditionalInits()). 140 addInitializationsFrom(condInfo.initsWhenFalse()); 141 } 142 } 143 144 FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( 146 (loopingContext.initsOnBreak.tagBits & 147 FlowInfo.UNREACHABLE) != 0 ? 148 loopingContext.initsOnBreak : 149 flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), isConditionOptimizedTrue, 151 exitBranch, 152 isConditionOptimizedFalse, 153 !isConditionTrue ); 154 mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); 155 return mergedInfo; 156 } 157 158 164 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 165 166 if ((bits & IsReachable) == 0) { 167 return; 168 } 169 int pc = codeStream.position; 170 Constant cst = this.condition.optimizedBooleanConstant(); 171 boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 172 if (isConditionOptimizedFalse) { 173 condition.generateCode(currentScope, codeStream, false); 174 if (mergedInitStateIndex != -1) { 176 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 177 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 178 } 179 codeStream.recordPositionsFrom(pc, this.sourceStart); 180 return; 181 } 182 183 breakLabel.initialize(codeStream); 184 185 if (continueLabel == null) { 187 if (condition.constant == Constant.NotAConstant) { 189 condition.generateOptimizedBoolean( 190 currentScope, 191 codeStream, 192 null, 193 breakLabel, 194 true); 195 } 196 } else { 197 continueLabel.initialize(codeStream); 198 if (!(((condition.constant != Constant.NotAConstant) 199 && (condition.constant.booleanValue() == true)) 200 || (action == null) 201 || action.isEmptyBlock())) { 202 int jumpPC = codeStream.position; 203 codeStream.goto_(continueLabel); 204 codeStream.recordPositionsFrom(jumpPC, condition.sourceStart); 205 } 206 } 207 BranchLabel actionLabel = new BranchLabel(codeStream); 209 if (action != null) { 210 actionLabel.tagBits |= BranchLabel.USED; 211 if (condIfTrueInitStateIndex != -1) { 213 codeStream.addDefinitelyAssignedVariables( 215 currentScope, 216 condIfTrueInitStateIndex); 217 } 218 actionLabel.place(); 219 action.generateCode(currentScope, codeStream); 220 if (preCondInitStateIndex != -1) { 222 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex); 223 } 224 } else { 225 actionLabel.place(); 226 } 227 if (continueLabel != null) { 229 continueLabel.place(); 230 condition.generateOptimizedBoolean( 231 currentScope, 232 codeStream, 233 actionLabel, 234 null, 235 true); 236 } 237 238 if (mergedInitStateIndex != -1) { 240 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 241 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 242 } 243 breakLabel.place(); 244 codeStream.recordPositionsFrom(pc, this.sourceStart); 245 } 246 247 public void resolve(BlockScope scope) { 248 249 TypeBinding type = condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); 250 condition.computeConversion(scope, type, type); 251 if (action != null) 252 action.resolve(scope); 253 } 254 255 public StringBuffer printStatement(int tab, StringBuffer output) { 256 257 printIndent(tab, output).append("while ("); condition.printExpression(0, output).append(')'); 259 if (action == null) 260 output.append(';'); 261 else 262 action.printStatement(tab + 1, output); 263 return output; 264 } 265 266 public void traverse( 267 ASTVisitor visitor, 268 BlockScope blockScope) { 269 270 if (visitor.visit(this, blockScope)) { 271 condition.traverse(visitor, blockScope); 272 if (action != null) 273 action.traverse(visitor, blockScope); 274 } 275 visitor.endVisit(this, blockScope); 276 } 277 } 278 | Popular Tags |