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.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
21 public class IfStatement extends Statement {
23 //this class represents the case of only one statement in
24 //either else and/or then branches.
26 public Expression condition;
27 public Statement thenStatement;
28 public Statement elseStatement;
32 // for local variables table attributes
33 int thenInitStateIndex = -1;
34 int elseInitStateIndex = -1;
35 int mergedInitStateIndex = -1;
39 Statement thenStatement,
43 this.condition = condition;
44 this.thenStatement = thenStatement;
51 Statement thenStatement,
52 Statement elseStatement,
56 this.condition = condition;
57 this.thenStatement = thenStatement;
58 this.elseStatement = elseStatement;
63 public FlowInfo analyseCode(
64 BlockScope currentScope,
65 FlowContext flowContext,
68 // process the condition
69 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
71 Constant cst = this.condition.optimizedBooleanConstant();
72 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
73 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
75 // process the THEN part
76 FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
77 if (isConditionOptimizedFalse) {
78 thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
80 if (this.thenStatement != null) {
81 // Save info for code gen
83 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
84 if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
86 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
89 // optimizing the jump around the ELSE part
90 this.thenExit = !thenFlowInfo.isReachable();
92 // process the ELSE part
93 FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
94 if (isConditionOptimizedTrue) {
95 elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
97 if (this.elseStatement != null) {
98 // Save info for code gen
100 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
101 if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
103 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
107 boolean elseExit = !elseFlowInfo.isReachable();
109 // merge THEN & ELSE initializations
111 // if (isConditionOptimizedTrue){
112 // if (!this.thenExit) {
113 // mergedInfo = thenFlowInfo;
115 // mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
118 // } else if (isConditionOptimizedFalse) {
120 // mergedInfo = elseFlowInfo;
122 // mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
126 // mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
128 if (isConditionOptimizedTrue){
129 if (!this.thenExit) {
130 mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
132 mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
135 } else if (isConditionOptimizedFalse) {
137 mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
139 mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
143 mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
146 mergedInitStateIndex =
147 currentScope.methodScope().recordInitializationStates(mergedInfo);
154 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
155 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
157 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
159 // if ((this.bits & IsReachableMASK) == 0) {
162 // int pc = codeStream.position;
163 // Label endifLabel = new Label(codeStream);
165 // // optimizing the then/else part code gen
167 // boolean hasThenPart =
168 // !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
169 // && cst.booleanValue() == false)
170 // || this.thenStatement == null
171 // || this.thenStatement.isEmptyBlock());
172 // boolean hasElsePart =
173 // !((cst != NotAConstant && cst.booleanValue() == true)
174 // || this.elseStatement == null
175 // || this.elseStatement.isEmptyBlock());
177 // if (hasThenPart) {
179 // // generate boolean condition
180 // this.condition.generateOptimizedBoolean(
184 // (falseLabel = new Label(codeStream)),
186 // // May loose some local variable initializations : affecting the local variable attributes
187 // if (thenInitStateIndex != -1) {
188 // codeStream.removeNotDefinitelyAssignedVariables(
190 // thenInitStateIndex);
191 // codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
193 // // generate then statement
194 // this.thenStatement.generateCode(currentScope, codeStream);
195 // // jump around the else statement
196 // if (hasElsePart && !thenExit) {
197 // this.thenStatement.branchChainTo(endifLabel);
198 // int position = codeStream.position;
199 // codeStream.goto_(endifLabel);
200 // codeStream.updateLastRecordedEndPC(position);
201 // //goto is tagged as part of the thenAction block
203 // falseLabel.place();
205 // if (hasElsePart) {
206 // // generate boolean condition
207 // this.condition.generateOptimizedBoolean(
214 // // generate condition side-effects
215 // this.condition.generateCode(currentScope, codeStream, false);
216 // codeStream.recordPositionsFrom(pc, this.sourceStart);
219 // // generate else statement
220 // if (hasElsePart) {
221 // // May loose some local variable initializations : affecting the local variable attributes
222 // if (elseInitStateIndex != -1) {
223 // codeStream.removeNotDefinitelyAssignedVariables(
225 // elseInitStateIndex);
226 // codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
228 // this.elseStatement.generateCode(currentScope, codeStream);
230 // endifLabel.place();
231 // // May loose some local variable initializations : affecting the local variable attributes
232 // if (mergedInitStateIndex != -1) {
233 // codeStream.removeNotDefinitelyAssignedVariables(
235 // mergedInitStateIndex);
237 // codeStream.recordPositionsFrom(pc, this.sourceStart);
240 public void resolve(BlockScope scope) {
242 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
243 condition.implicitWidening(type, type);
244 if (thenStatement != null)
245 thenStatement.resolve(scope);
246 if (elseStatement != null)
247 elseStatement.resolve(scope);
250 public String toString(int tab) {
252 String inFront, s = tabString(tab);
254 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
255 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
256 if (elseStatement != null)
257 s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
261 public void traverse(
262 IAbstractSyntaxTreeVisitor visitor,
263 BlockScope blockScope) {
265 if (visitor.visit(this, blockScope)) {
266 condition.traverse(visitor, blockScope);
267 if (thenStatement != null)
268 thenStatement.traverse(visitor, blockScope);
269 if (elseStatement != null)
270 elseStatement.traverse(visitor, blockScope);
272 visitor.endVisit(this, blockScope);