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;
26 public Statement thenStatement;
27 public Statement elseStatement;
28 public Expression[] elseifConditions;
29 public Statement[] elseifStatements;
30 public boolean checkUnreachable;
34 // for local variables table attributes
35 int thenInitStateIndex = -1;
36 int elseInitStateIndex = -1;
37 int mergedInitStateIndex = -1;
41 Statement thenStatement,
45 this.condition = condition;
46 this.thenStatement = thenStatement;
49 checkUnreachable = true;
54 Statement thenStatement,
55 Statement elseStatement,
59 this.condition = condition;
60 this.thenStatement = thenStatement;
61 this.elseStatement = elseStatement;
64 checkUnreachable = true;
67 public FlowInfo analyseCode(
68 BlockScope currentScope,
69 FlowContext flowContext,
72 // process the condition
73 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
75 Constant cst = this.condition.optimizedBooleanConstant();
76 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
77 boolean isConditionOptimizedFalse = cst != NotAConstant && 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
87 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
88 if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
90 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
93 // optimizing the jump around the ELSE part
94 this.thenExit = !thenFlowInfo.isReachable();
96 // process the ELSE part
97 FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
98 if (isConditionOptimizedTrue) {
99 elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
101 if (this.elseStatement != null) {
102 // Save info for code gen
104 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
105 if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
107 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
111 boolean elseExit = !elseFlowInfo.isReachable();
113 // merge THEN & ELSE initializations
115 // if (isConditionOptimizedTrue){
116 // if (!this.thenExit) {
117 // mergedInfo = thenFlowInfo;
119 // mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
122 // } else if (isConditionOptimizedFalse) {
124 // mergedInfo = elseFlowInfo;
126 // mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
130 // mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
132 if (isConditionOptimizedTrue){
133 if (!this.thenExit) {
134 mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
136 mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
139 } else if (isConditionOptimizedFalse) {
141 mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
143 mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
147 mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
150 mergedInitStateIndex =
151 currentScope.methodScope().recordInitializationStates(mergedInfo);
158 * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
159 * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
161 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
163 // if ((this.bits & IsReachableMASK) == 0) {
166 // int pc = codeStream.position;
167 // Label endifLabel = new Label(codeStream);
169 // // optimizing the then/else part code gen
171 // boolean hasThenPart =
172 // !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
173 // && cst.booleanValue() == false)
174 // || this.thenStatement == null
175 // || this.thenStatement.isEmptyBlock());
176 // boolean hasElsePart =
177 // !((cst != NotAConstant && cst.booleanValue() == true)
178 // || this.elseStatement == null
179 // || this.elseStatement.isEmptyBlock());
181 // if (hasThenPart) {
183 // // generate boolean condition
184 // this.condition.generateOptimizedBoolean(
188 // (falseLabel = new Label(codeStream)),
190 // // May loose some local variable initializations : affecting the local variable attributes
191 // if (thenInitStateIndex != -1) {
192 // codeStream.removeNotDefinitelyAssignedVariables(
194 // thenInitStateIndex);
195 // codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
197 // // generate then statement
198 // this.thenStatement.generateCode(currentScope, codeStream);
199 // // jump around the else statement
200 // if (hasElsePart && !thenExit) {
201 // this.thenStatement.branchChainTo(endifLabel);
202 // int position = codeStream.position;
203 // codeStream.goto_(endifLabel);
204 // codeStream.updateLastRecordedEndPC(position);
205 // //goto is tagged as part of the thenAction block
207 // falseLabel.place();
209 // if (hasElsePart) {
210 // // generate boolean condition
211 // this.condition.generateOptimizedBoolean(
218 // // generate condition side-effects
219 // this.condition.generateCode(currentScope, codeStream, false);
220 // codeStream.recordPositionsFrom(pc, this.sourceStart);
223 // // generate else statement
224 // if (hasElsePart) {
225 // // May loose some local variable initializations : affecting the local variable attributes
226 // if (elseInitStateIndex != -1) {
227 // codeStream.removeNotDefinitelyAssignedVariables(
229 // elseInitStateIndex);
230 // codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
232 // this.elseStatement.generateCode(currentScope, codeStream);
234 // endifLabel.place();
235 // // May loose some local variable initializations : affecting the local variable attributes
236 // if (mergedInitStateIndex != -1) {
237 // codeStream.removeNotDefinitelyAssignedVariables(
239 // mergedInitStateIndex);
241 // codeStream.recordPositionsFrom(pc, this.sourceStart);
243 public StringBuffer printStatement(int indent, StringBuffer output) {
245 printIndent(indent, output).append("if ("); //$NON-NLS-1$
246 condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$
247 thenStatement.printStatement(indent + 2, output);
248 if (elseStatement != null) {
250 printIndent(indent, output);
251 output.append("else\n"); //$NON-NLS-1$
252 elseStatement.printStatement(indent + 2, output);
256 public void resolve(BlockScope scope) {
258 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
259 condition.implicitWidening(type, type);
260 if (thenStatement != null)
261 thenStatement.resolve(scope);
262 if (elseStatement != null)
263 elseStatement.resolve(scope);
266 public String toString(int tab) {
268 String inFront, s = tabString(tab);
270 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
271 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
272 if (elseStatement != null)
273 s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
277 public void traverse(
279 BlockScope blockScope) {
281 if (visitor.visit(this, blockScope)) {
282 condition.traverse(visitor, blockScope);
283 if (thenStatement != null)
284 thenStatement.traverse(visitor, blockScope);
285 if (elseStatement != null)
286 elseStatement.traverse(visitor, blockScope);
288 visitor.endVisit(this, blockScope);