KickJava   Java API By Example, From Geeks To Geeks.

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


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.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     //when there is no local declaration, there is no need of a new scope
28
//scope is positioned either to a new scope, or to the "upper"scope (see resolveType)
29
public BlockScope scope;
30
31     private BranchLabel breakLabel, continueLabel;
32
33     // for local variables table attributes
34
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         // remember useful empty statement
55
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         // process the initializations
70
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         // process the condition
87
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         // process the action
102
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; // for(;false;p());
117
}
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             // code generation can be optimized when no need to continue in the loop
146
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         // for increments
162
FlowInfo exitBranch = flowInfo.copy();
163         // recover null inits from before condition analysis
164
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         // nulls checks
187
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         //end of loop
199
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
200                 (loopingContext.initsOnBreak.tagBits &
201                     FlowInfo.UNREACHABLE) != 0 ?
202                     loopingContext.initsOnBreak :
203                     flowInfo.addInitializationsFrom(loopingContext.initsOnBreak), // recover upstream null info
204
isConditionOptimizedTrue,
205                 exitBranch,
206                 isConditionOptimizedFalse,
207                 !isConditionTrue /*for(;;){}while(true); unreachable(); */);
208         mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
209         return mergedInfo;
210     }
211
212     /**
213      * For statement code generation
214      *
215      * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
216      * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
217      */

218     public void generateCode(BlockScope currentScope, CodeStream codeStream) {
219
220         if ((bits & IsReachable) == 0) {
221             return;
222         }
223         int pc = codeStream.position;
224
225         // generate the initializations
226
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             // May loose some local variable initializations : affecting the local variable attributes
236
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         // label management
248
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             // jump over the actionBlock
260
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         // generate the loop action
271
if (action != null) {
272             // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
273
if (condIfTrueInitStateIndex != -1) {
274                 // insert all locals initialized inside the condition into the action generated prior to the condition
275
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         // continuation point
289
if (continueLabel != null) {
290             continueLabel.place();
291             // generate the increments for next iteration
292
if (increments != null) {
293                 for (int i = 0, max = increments.length; i < max; i++) {
294                     increments[i].generateCode(scope, codeStream);
295                 }
296             }
297             // May loose some local variable initializations : affecting the local variable attributes
298
if (preCondInitStateIndex != -1) {
299                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
300             }
301             // generate the condition
302
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             // May loose some local variable initializations : affecting the local variable attributes
311
if (preCondInitStateIndex != -1) {
312                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
313             }
314         }
315
316
317         // May loose some local variable initializations : affecting the local variable attributes
318
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 JavaDoc printStatement(int tab, StringBuffer JavaDoc output) {
330
331         printIndent(tab, output).append("for ("); //$NON-NLS-1$
332
//inits
333
if (initializations != null) {
334             for (int i = 0; i < initializations.length; i++) {
335                 //nice only with expressions
336
if (i > 0) output.append(", "); //$NON-NLS-1$
337
initializations[i].print(0, output);
338             }
339         }
340         output.append("; "); //$NON-NLS-1$
341
//cond
342
if (condition != null) condition.printExpression(0, output);
343         output.append("; "); //$NON-NLS-1$
344
//updates
345
if (increments != null) {
346             for (int i = 0; i < increments.length; i++) {
347                 if (i > 0) output.append(", "); //$NON-NLS-1$
348
increments[i].print(0, output);
349             }
350         }
351         output.append(") "); //$NON-NLS-1$
352
//block
353
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         // use the scope that will hold the init declarations
365
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