KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.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     // for local variables table attributes
27
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     // remember useful empty statement
36
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     // we need to collect the contribution to nulls of the coming paths through the
61
// loop, be they falling through normally or branched to break, continue labels
62
// or catch blocks
63
if ((this.action != null) && !this.action.isEmptyBlock()) {
64         actionInfo = this.action.
65             analyseCode(currentScope, loopingContext, actionInfo).
66             unconditionalInits();
67
68         // code generation can be optimized when no need to continue in the loop
69
if ((actionInfo.tagBits &
70                 loopingContext.initsOnContinue.tagBits &
71                 FlowInfo.UNREACHABLE) != 0) {
72             this.continueLabel = null;
73         }
74     }
75     /* Reset reach mode, to address following scenario.
76      * final blank;
77      * do { if (true) break; else blank = 0; } while(false);
78      * blank = 1; // may be initialized already
79      */

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     // end of loop
104
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
105             (loopingContext.initsOnBreak.tagBits &
106                 FlowInfo.UNREACHABLE) != 0 ?
107                 loopingContext.initsOnBreak :
108                 flowInfo.unconditionalCopy().addInitializationsFrom(loopingContext.initsOnBreak),
109                     // recover upstream null info
110
isConditionOptimizedTrue,
111             (condInfo.tagBits & FlowInfo.UNREACHABLE) == 0 ?
112                     flowInfo.addInitializationsFrom(condInfo.initsWhenFalse()) : condInfo,
113                 // recover null inits from before condition analysis
114
false, // never consider opt false case for DO loop, since break can always occur (47776)
115
!isConditionTrue /*do{}while(true); unreachable(); */);
116     this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
117     return mergedInfo;
118 }
119
120 /**
121  * Do statement code generation
122  *
123  */

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     // labels management
131
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     // generate action
141
if (this.action != null) {
142         this.action.generateCode(currentScope, codeStream);
143     }
144     // continue label (135602)
145
if (hasContinueLabel) {
146         this.continueLabel.place();
147     }
148     // generate condition
149
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     // May loose some local variable initializations : affecting the local variable attributes
162
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 JavaDoc printStatement(int indent, StringBuffer JavaDoc output) {
174     printIndent(indent, output).append("do"); //$NON-NLS-1$
175
if (this.action == null)
176         output.append(" ;\n"); //$NON-NLS-1$
177
else {
178         output.append('\n');
179         this.action.printStatement(indent + 1, output).append('\n');
180     }
181     output.append("while ("); //$NON-NLS-1$
182
return this.condition.printExpression(0, output).append(");"); //$NON-NLS-1$
183
}
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