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.codegen.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.lookup.*; 18 19 public class DoStatement extends Statement { 20 21 public Expression condition; 22 public Statement action; 23 24 private BranchLabel breakLabel, continueLabel; 25 26 int mergedInitStateIndex = -1; 28 29 public DoStatement(Expression condition, Statement action, int sourceStart, int sourceEnd) { 30 31 this.sourceStart = sourceStart; 32 this.sourceEnd = sourceEnd; 33 this.condition = condition; 34 this.action = action; 35 if (action instanceof EmptyStatement) action.bits |= ASTNode.IsUsefulEmptyStatement; 37 } 38 39 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 40 this.breakLabel = new BranchLabel(); 41 this.continueLabel = new BranchLabel(); 42 LoopingFlowContext loopingContext = 43 new LoopingFlowContext( 44 flowContext, 45 flowInfo, 46 this, 47 this.breakLabel, 48 this.continueLabel, 49 currentScope); 50 51 Constant cst = this.condition.constant; 52 boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; 53 cst = this.condition.optimizedBooleanConstant(); 54 boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; 55 boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 56 57 int previousMode = flowInfo.reachMode(); 58 59 UnconditionalFlowInfo actionInfo = flowInfo.nullInfoLessUnconditionalCopy(); 60 if ((this.action != null) && !this.action.isEmptyBlock()) { 64 actionInfo = this.action. 65 analyseCode(currentScope, loopingContext, actionInfo). 66 unconditionalInits(); 67 68 if ((actionInfo.tagBits & 70 loopingContext.initsOnContinue.tagBits & 71 FlowInfo.UNREACHABLE) != 0) { 72 this.continueLabel = null; 73 } 74 } 75 80 actionInfo.setReachMode(previousMode); 81 82 LoopingFlowContext condLoopContext; 83 FlowInfo condInfo = 84 this.condition.analyseCode( 85 currentScope, 86 (condLoopContext = 87 new LoopingFlowContext(flowContext, flowInfo, this, null, 88 null, currentScope)), 89 (this.action == null 90 ? actionInfo 91 : (actionInfo.mergedWith(loopingContext.initsOnContinue))).copy()); 92 if (!isConditionOptimizedFalse && this.continueLabel != null) { 93 loopingContext.complainOnDeferredFinalChecks(currentScope, condInfo); 94 condLoopContext.complainOnDeferredFinalChecks(currentScope, condInfo); 95 loopingContext.complainOnDeferredNullChecks(currentScope, 96 flowInfo.unconditionalCopy().addPotentialNullInfoFrom( 97 condInfo.initsWhenTrue().unconditionalInits())); 98 condLoopContext.complainOnDeferredNullChecks(currentScope, 99 actionInfo.addPotentialNullInfoFrom( 100 condInfo.initsWhenTrue().unconditionalInits())); 101 } 102 103 FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( 105 (loopingContext.initsOnBreak.tagBits & 106 FlowInfo.UNREACHABLE) != 0 ? 107 loopingContext.initsOnBreak : 108 flowInfo.unconditionalCopy().addInitializationsFrom(loopingContext.initsOnBreak), 109 isConditionOptimizedTrue, 111 (condInfo.tagBits & FlowInfo.UNREACHABLE) == 0 ? 112 flowInfo.addInitializationsFrom(condInfo.initsWhenFalse()) : condInfo, 113 false, !isConditionTrue ); 116 this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); 117 return mergedInfo; 118 } 119 120 124 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 125 if ((this.bits & ASTNode.IsReachable) == 0) { 126 return; 127 } 128 int pc = codeStream.position; 129 130 BranchLabel actionLabel = new BranchLabel(codeStream); 132 if (this.action != null) actionLabel.tagBits |= BranchLabel.USED; 133 actionLabel.place(); 134 this.breakLabel.initialize(codeStream); 135 boolean hasContinueLabel = this.continueLabel != null; 136 if (hasContinueLabel) { 137 this.continueLabel.initialize(codeStream); 138 } 139 140 if (this.action != null) { 142 this.action.generateCode(currentScope, codeStream); 143 } 144 if (hasContinueLabel) { 146 this.continueLabel.place(); 147 } 148 Constant cst = this.condition.optimizedBooleanConstant(); 150 boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 151 if (isConditionOptimizedFalse){ 152 this.condition.generateCode(currentScope, codeStream, false); 153 } else if (hasContinueLabel) { 154 this.condition.generateOptimizedBoolean( 155 currentScope, 156 codeStream, 157 actionLabel, 158 null, 159 true); 160 } 161 if (this.mergedInitStateIndex != -1) { 163 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); 164 codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); 165 } 166 if (this.breakLabel.forwardReferenceCount() > 0) { 167 this.breakLabel.place(); 168 } 169 170 codeStream.recordPositionsFrom(pc, this.sourceStart); 171 } 172 173 public StringBuffer printStatement(int indent, StringBuffer output) { 174 printIndent(indent, output).append("do"); if (this.action == null) 176 output.append(" ;\n"); else { 178 output.append('\n'); 179 this.action.printStatement(indent + 1, output).append('\n'); 180 } 181 output.append("while ("); return this.condition.printExpression(0, output).append(");"); } 184 185 public void resolve(BlockScope scope) { 186 TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); 187 this.condition.computeConversion(scope, type, type); 188 if (this.action != null) 189 this.action.resolve(scope); 190 } 191 192 public void traverse(ASTVisitor visitor, BlockScope scope) { 193 if (visitor.visit(this, scope)) { 194 if (this.action != null) { 195 this.action.traverse(visitor, scope); 196 } 197 this.condition.traverse(visitor, scope); 198 } 199 visitor.endVisit(this, scope); 200 } 201 } 202 | Popular Tags |