KickJava   Java API By Example, From Geeks To Geeks.

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


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 IfStatement extends Statement {
20     
21     //this class represents the case of only one statement in
22
//either else and/or then branches.
23

24     public Expression condition;
25     public Statement thenStatement;
26     public Statement elseStatement;
27
28     // for local variables table attributes
29
int thenInitStateIndex = -1;
30     int elseInitStateIndex = -1;
31     int mergedInitStateIndex = -1;
32
33     public IfStatement(Expression condition, Statement thenStatement, int sourceStart, int sourceEnd) {
34
35         this.condition = condition;
36         this.thenStatement = thenStatement;
37         // remember useful empty statement
38
if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement;
39         this.sourceStart = sourceStart;
40         this.sourceEnd = sourceEnd;
41     }
42
43     public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement, int sourceStart, int sourceEnd) {
44
45         this.condition = condition;
46         this.thenStatement = thenStatement;
47         // remember useful empty statement
48
if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement;
49         this.elseStatement = elseStatement;
50         if (elseStatement instanceof IfStatement) elseStatement.bits |= IsElseIfStatement;
51         if (elseStatement instanceof EmptyStatement) elseStatement.bits |= IsUsefulEmptyStatement;
52         this.sourceStart = sourceStart;
53         this.sourceEnd = sourceEnd;
54     }
55
56     public FlowInfo analyseCode(
57         BlockScope currentScope,
58         FlowContext flowContext,
59         FlowInfo flowInfo) {
60
61         // process the condition
62
FlowInfo conditionFlowInfo =
63             condition.analyseCode(currentScope, flowContext, flowInfo);
64
65         Constant cst = this.condition.optimizedBooleanConstant();
66         boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
67         boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
68         
69         // process the THEN part
70
FlowInfo thenFlowInfo = conditionFlowInfo.safeInitsWhenTrue();
71         if (isConditionOptimizedFalse) {
72             thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
73         }
74         FlowInfo elseFlowInfo = conditionFlowInfo.initsWhenFalse();
75         if (isConditionOptimizedTrue) {
76             elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
77         }
78         if (this.thenStatement != null) {
79             // Save info for code gen
80
thenInitStateIndex =
81                 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
82             if (!thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) {
83                 thenFlowInfo =
84                     thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
85             }
86         }
87         // code gen: optimizing the jump around the ELSE part
88
if ((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) {
89             this.bits |= ASTNode.ThenExit;
90         }
91
92         // process the ELSE part
93
if (this.elseStatement != null) {
94             // signal else clause unnecessarily nested, tolerate else-if code pattern
95
if (thenFlowInfo == FlowInfo.DEAD_END
96                     && (this.bits & IsElseIfStatement) == 0 // else of an else-if
97
&& !(this.elseStatement instanceof IfStatement)) {
98                 currentScope.problemReporter().unnecessaryElse(this.elseStatement);
99             }
100             // Save info for code gen
101
elseInitStateIndex =
102                 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
103             if (!elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) {
104                 elseFlowInfo =
105                     elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
106             }
107         }
108
109         // merge THEN & ELSE initializations
110
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
111             thenFlowInfo,
112             isConditionOptimizedTrue,
113             elseFlowInfo,
114             isConditionOptimizedFalse,
115             true /*if(true){ return; } fake-reachable(); */);
116         mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
117         return mergedInfo;
118     }
119
120     /**
121      * If code generation
122      *
123      * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
124      * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
125      */

126     public void generateCode(BlockScope currentScope, CodeStream codeStream) {
127
128         if ((this.bits & IsReachable) == 0) {
129             return;
130         }
131         int pc = codeStream.position;
132         BranchLabel endifLabel = new BranchLabel(codeStream);
133
134         // optimizing the then/else part code gen
135
Constant cst;
136         boolean hasThenPart =
137             !(((cst = this.condition.optimizedBooleanConstant()) != Constant.NotAConstant
138                     && cst.booleanValue() == false)
139                 || this.thenStatement == null
140                 || this.thenStatement.isEmptyBlock());
141         boolean hasElsePart =
142             !((cst != Constant.NotAConstant && cst.booleanValue() == true)
143                 || this.elseStatement == null
144                 || this.elseStatement.isEmptyBlock());
145         if (hasThenPart) {
146             BranchLabel falseLabel = null;
147             // generate boolean condition
148
this.condition.generateOptimizedBoolean(
149                 currentScope,
150                 codeStream,
151                 null,
152                 hasElsePart ? (falseLabel = new BranchLabel(codeStream)) : endifLabel,
153                 true/*cst == Constant.NotAConstant*/);
154             // May loose some local variable initializations : affecting the local variable attributes
155
if (thenInitStateIndex != -1) {
156                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
157                 codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
158             }
159             // generate then statement
160
this.thenStatement.generateCode(currentScope, codeStream);
161             // jump around the else statement
162
if (hasElsePart) {
163                 if ((this.bits & ASTNode.ThenExit) == 0) {
164                     this.thenStatement.branchChainTo(endifLabel);
165                     int position = codeStream.position;
166                     codeStream.goto_(endifLabel);
167                     //goto is tagged as part of the thenAction block
168
codeStream.updateLastRecordedEndPC((this.thenStatement instanceof Block) ? ((Block) this.thenStatement).scope : currentScope, position);
169                     // generate else statement
170
}
171                 // May loose some local variable initializations : affecting the local variable attributes
172
if (elseInitStateIndex != -1) {
173                     codeStream.removeNotDefinitelyAssignedVariables(
174                         currentScope,
175                         elseInitStateIndex);
176                     codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
177                 }
178                 if (falseLabel != null) falseLabel.place();
179                 this.elseStatement.generateCode(currentScope, codeStream);
180             }
181         } else if (hasElsePart) {
182             // generate boolean condition
183
this.condition.generateOptimizedBoolean(
184                 currentScope,
185                 codeStream,
186                 endifLabel,
187                 null,
188                 true/*cst == Constant.NotAConstant*/);
189             // generate else statement
190
// May loose some local variable initializations : affecting the local variable attributes
191
if (elseInitStateIndex != -1) {
192                 codeStream.removeNotDefinitelyAssignedVariables(
193                     currentScope,
194                     elseInitStateIndex);
195                 codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
196             }
197             this.elseStatement.generateCode(currentScope, codeStream);
198         } else {
199             // generate condition side-effects
200
this.condition.generateCode(currentScope, codeStream, false);
201             codeStream.recordPositionsFrom(pc, this.sourceStart);
202         }
203         // May loose some local variable initializations : affecting the local variable attributes
204
if (mergedInitStateIndex != -1) {
205             codeStream.removeNotDefinitelyAssignedVariables(
206                 currentScope,
207                 mergedInitStateIndex);
208             codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
209         }
210         endifLabel.place();
211         codeStream.recordPositionsFrom(pc, this.sourceStart);
212     }
213
214     public StringBuffer JavaDoc printStatement(int indent, StringBuffer JavaDoc output) {
215
216         printIndent(indent, output).append("if ("); //$NON-NLS-1$
217
condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$
218
thenStatement.printStatement(indent + 2, output);
219         if (elseStatement != null) {
220             output.append('\n');
221             printIndent(indent, output);
222             output.append("else\n"); //$NON-NLS-1$
223
elseStatement.printStatement(indent + 2, output);
224         }
225         return output;
226     }
227
228     public void resolve(BlockScope scope) {
229
230         TypeBinding type = condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
231         condition.computeConversion(scope, type, type);
232         if (thenStatement != null)
233             thenStatement.resolve(scope);
234         if (elseStatement != null)
235             elseStatement.resolve(scope);
236     }
237
238     public void traverse(
239         ASTVisitor visitor,
240         BlockScope blockScope) {
241
242         if (visitor.visit(this, blockScope)) {
243             condition.traverse(visitor, blockScope);
244             if (thenStatement != null)
245                 thenStatement.traverse(visitor, blockScope);
246             if (elseStatement != null)
247                 elseStatement.traverse(visitor, blockScope);
248         }
249         visitor.endVisit(this, blockScope);
250     }
251 }
252
Popular Tags