1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
20 public class IfStatement extends Statement {
22 // this class represents the case of only one statement in
23 // either else and/or then branches.
25 public Expression condition;
27 public Statement thenStatement;
29 public Statement elseStatement;
31 public Expression[] elseifConditions;
33 public Statement[] elseifStatements;
35 public boolean checkUnreachable;
39 // for local variables table attributes
40 int thenInitStateIndex = -1;
42 int elseInitStateIndex = -1;
44 int mergedInitStateIndex = -1;
46 public IfStatement(Expression condition, Statement thenStatement, int s,
49 this.condition = condition;
50 this.thenStatement = thenStatement;
53 checkUnreachable = true;
56 public IfStatement(Expression condition, Statement thenStatement,
57 Statement elseStatement, int s, int e) {
59 this.condition = condition;
60 this.thenStatement = thenStatement;
61 this.elseStatement = elseStatement;
64 checkUnreachable = true;
67 public FlowInfo analyseCode(BlockScope currentScope,
68 FlowContext flowContext, FlowInfo flowInfo) {
70 // process the condition
71 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
73 Constant cst = this.condition.optimizedBooleanConstant();
74 boolean isConditionOptimizedTrue = cst != NotAConstant
75 && cst.booleanValue() == true;
76 boolean isConditionOptimizedFalse = cst != NotAConstant
77 && cst.booleanValue() == false;
79 // process the THEN part
80 FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
81 if (isConditionOptimizedFalse) {
82 thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
84 if (this.thenStatement != null) {
85 // Save info for code gen
86 thenInitStateIndex = currentScope.methodScope()
87 .recordInitializationStates(thenFlowInfo);
88 if (!thenFlowInfo.complainIfUnreachable(thenStatement,
89 currentScope, false)) {
90 thenFlowInfo = thenStatement.analyseCode(currentScope,
91 flowContext, thenFlowInfo);
95 // optimizing the jump around the ELSE part
96 this.thenExit = !thenFlowInfo.isReachable();
98 // process the ELSE part
99 FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
100 if (isConditionOptimizedTrue) {
101 elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
103 if (this.elseStatement != null) {
104 // Save info for code gen
105 elseInitStateIndex = currentScope.methodScope()
106 .recordInitializationStates(elseFlowInfo);
107 if (!elseFlowInfo.complainIfUnreachable(elseStatement,
108 currentScope, false)) {
109 elseFlowInfo = elseStatement.analyseCode(currentScope,
110 flowContext, elseFlowInfo);
114 boolean elseExit = !elseFlowInfo.isReachable();
116 // merge THEN & ELSE initializations
118 // if (isConditionOptimizedTrue){
119 // if (!this.thenExit) {
120 // mergedInfo = thenFlowInfo;
122 // mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
125 // } else if (isConditionOptimizedFalse) {
127 // mergedInfo = elseFlowInfo;
129 // mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
134 // thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
136 if (isConditionOptimizedTrue) {
137 if (!this.thenExit) {
138 mergedInfo = thenFlowInfo
139 .addPotentialInitializationsFrom(elseFlowInfo);
141 mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
144 } else if (isConditionOptimizedFalse) {
146 mergedInfo = elseFlowInfo
147 .addPotentialInitializationsFrom(thenFlowInfo);
149 mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
153 mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo
154 .unconditionalInits());
157 mergedInitStateIndex = currentScope.methodScope()
158 .recordInitializationStates(mergedInfo);
165 * @param currentScope
166 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
168 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
170 // public void generateCode(BlockScope currentScope, CodeStream codeStream)
173 // if ((this.bits & IsReachableMASK) == 0) {
176 // int pc = codeStream.position;
177 // Label endifLabel = new Label(codeStream);
179 // // optimizing the then/else part code gen
181 // boolean hasThenPart =
182 // !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
183 // && cst.booleanValue() == false)
184 // || this.thenStatement == null
185 // || this.thenStatement.isEmptyBlock());
186 // boolean hasElsePart =
187 // !((cst != NotAConstant && cst.booleanValue() == true)
188 // || this.elseStatement == null
189 // || this.elseStatement.isEmptyBlock());
191 // if (hasThenPart) {
193 // // generate boolean condition
194 // this.condition.generateOptimizedBoolean(
198 // (falseLabel = new Label(codeStream)),
200 // // May loose some local variable initializations : affecting the local
201 // variable attributes
202 // if (thenInitStateIndex != -1) {
203 // codeStream.removeNotDefinitelyAssignedVariables(
205 // thenInitStateIndex);
206 // codeStream.addDefinitelyAssignedVariables(currentScope,
207 // thenInitStateIndex);
209 // // generate then statement
210 // this.thenStatement.generateCode(currentScope, codeStream);
211 // // jump around the else statement
212 // if (hasElsePart && !thenExit) {
213 // this.thenStatement.branchChainTo(endifLabel);
214 // int position = codeStream.position;
215 // codeStream.goto_(endifLabel);
216 // codeStream.updateLastRecordedEndPC(position);
217 // //goto is tagged as part of the thenAction block
219 // falseLabel.place();
221 // if (hasElsePart) {
222 // // generate boolean condition
223 // this.condition.generateOptimizedBoolean(
230 // // generate condition side-effects
231 // this.condition.generateCode(currentScope, codeStream, false);
232 // codeStream.recordPositionsFrom(pc, this.sourceStart);
235 // // generate else statement
236 // if (hasElsePart) {
237 // // May loose some local variable initializations : affecting the local
238 // variable attributes
239 // if (elseInitStateIndex != -1) {
240 // codeStream.removeNotDefinitelyAssignedVariables(
242 // elseInitStateIndex);
243 // codeStream.addDefinitelyAssignedVariables(currentScope,
244 // elseInitStateIndex);
246 // this.elseStatement.generateCode(currentScope, codeStream);
248 // endifLabel.place();
249 // // May loose some local variable initializations : affecting the local
250 // variable attributes
251 // if (mergedInitStateIndex != -1) {
252 // codeStream.removeNotDefinitelyAssignedVariables(
254 // mergedInitStateIndex);
256 // codeStream.recordPositionsFrom(pc, this.sourceStart);
258 public StringBuffer printStatement(int indent, StringBuffer output) {
260 printIndent(indent, output).append("if ("); //$NON-NLS-1$
261 condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$
262 thenStatement.printStatement(indent + 2, output);
263 if (elseStatement != null) {
265 printIndent(indent, output);
266 output.append("else\n"); //$NON-NLS-1$
267 elseStatement.printStatement(indent + 2, output);
272 public void resolve(BlockScope scope) {
274 TypeBinding type = condition
275 .resolveTypeExpecting(scope, BooleanBinding);
276 condition.implicitWidening(type, type);
277 if (thenStatement != null)
278 thenStatement.resolve(scope);
279 if (elseStatement != null)
280 elseStatement.resolve(scope);
283 public String toString(int tab) {
285 String inFront, s = tabString(tab);
287 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
288 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
289 if (elseStatement != null)
291 + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
295 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
297 if (visitor.visit(this, blockScope)) {
298 condition.traverse(visitor, blockScope);
299 if (thenStatement != null)
300 thenStatement.traverse(visitor, blockScope);
301 if (elseStatement != null)
302 elseStatement.traverse(visitor, blockScope);
304 visitor.endVisit(this, blockScope);