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.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;
31 // for local variables table attributes
32 int thenInitStateIndex = -1;
33 int elseInitStateIndex = -1;
34 int mergedInitStateIndex = -1;
38 Statement thenStatement,
42 this.condition = condition;
43 this.thenStatement = thenStatement;
50 Statement thenStatement,
51 Statement elseStatement,
55 this.condition = condition;
56 this.thenStatement = thenStatement;
57 this.elseStatement = elseStatement;
62 public FlowInfo analyseCode(
63 BlockScope currentScope,
64 FlowContext flowContext,
67 // process the condition
68 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
70 Constant cst = this.condition.optimizedBooleanConstant();
71 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
72 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
74 // process the THEN part
75 FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
76 if (isConditionOptimizedFalse) {
77 thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
79 if (this.thenStatement != null) {
80 // Save info for code gen
82 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
83 if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
85 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
88 // optimizing the jump around the ELSE part
89 this.thenExit = !thenFlowInfo.isReachable();
91 // process the ELSE part
92 FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
93 if (isConditionOptimizedTrue) {
94 elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
96 if (this.elseStatement != null) {
97 // Save info for code gen
99 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
100 if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
102 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
106 boolean elseExit = !elseFlowInfo.isReachable();
108 // merge THEN & ELSE initializations
110 // if (isConditionOptimizedTrue){
111 // if (!this.thenExit) {
112 // mergedInfo = thenFlowInfo;
114 // mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
117 // } else if (isConditionOptimizedFalse) {
119 // mergedInfo = elseFlowInfo;
121 // mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
125 // mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
127 if (isConditionOptimizedTrue){
128 if (!this.thenExit) {
129 mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
131 mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
134 } else if (isConditionOptimizedFalse) {
136 mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
138 mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
142 mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
145 mergedInitStateIndex =
146 currentScope.methodScope().recordInitializationStates(mergedInfo);
153 * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
154 * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
156 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
158 // if ((this.bits & IsReachableMASK) == 0) {
161 // int pc = codeStream.position;
162 // Label endifLabel = new Label(codeStream);
164 // // optimizing the then/else part code gen
166 // boolean hasThenPart =
167 // !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
168 // && cst.booleanValue() == false)
169 // || this.thenStatement == null
170 // || this.thenStatement.isEmptyBlock());
171 // boolean hasElsePart =
172 // !((cst != NotAConstant && cst.booleanValue() == true)
173 // || this.elseStatement == null
174 // || this.elseStatement.isEmptyBlock());
176 // if (hasThenPart) {
178 // // generate boolean condition
179 // this.condition.generateOptimizedBoolean(
183 // (falseLabel = new Label(codeStream)),
185 // // May loose some local variable initializations : affecting the local variable attributes
186 // if (thenInitStateIndex != -1) {
187 // codeStream.removeNotDefinitelyAssignedVariables(
189 // thenInitStateIndex);
190 // codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
192 // // generate then statement
193 // this.thenStatement.generateCode(currentScope, codeStream);
194 // // jump around the else statement
195 // if (hasElsePart && !thenExit) {
196 // this.thenStatement.branchChainTo(endifLabel);
197 // int position = codeStream.position;
198 // codeStream.goto_(endifLabel);
199 // codeStream.updateLastRecordedEndPC(position);
200 // //goto is tagged as part of the thenAction block
202 // falseLabel.place();
204 // if (hasElsePart) {
205 // // generate boolean condition
206 // this.condition.generateOptimizedBoolean(
213 // // generate condition side-effects
214 // this.condition.generateCode(currentScope, codeStream, false);
215 // codeStream.recordPositionsFrom(pc, this.sourceStart);
218 // // generate else statement
219 // if (hasElsePart) {
220 // // May loose some local variable initializations : affecting the local variable attributes
221 // if (elseInitStateIndex != -1) {
222 // codeStream.removeNotDefinitelyAssignedVariables(
224 // elseInitStateIndex);
225 // codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
227 // this.elseStatement.generateCode(currentScope, codeStream);
229 // endifLabel.place();
230 // // May loose some local variable initializations : affecting the local variable attributes
231 // if (mergedInitStateIndex != -1) {
232 // codeStream.removeNotDefinitelyAssignedVariables(
234 // mergedInitStateIndex);
236 // codeStream.recordPositionsFrom(pc, this.sourceStart);
238 public StringBuffer printStatement(int indent, StringBuffer output) {
240 printIndent(indent, output).append("if ("); //$NON-NLS-1$
241 condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$
242 thenStatement.printStatement(indent + 2, output);
243 if (elseStatement != null) {
245 printIndent(indent, output);
246 output.append("else\n"); //$NON-NLS-1$
247 elseStatement.printStatement(indent + 2, output);
251 public void resolve(BlockScope scope) {
253 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
254 condition.implicitWidening(type, type);
255 if (thenStatement != null)
256 thenStatement.resolve(scope);
257 if (elseStatement != null)
258 elseStatement.resolve(scope);
261 public String toString(int tab) {
263 String inFront, s = tabString(tab);
265 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
266 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
267 if (elseStatement != null)
268 s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
272 public void traverse(
274 BlockScope blockScope) {
276 if (visitor.visit(this, blockScope)) {
277 condition.traverse(visitor, blockScope);
278 if (thenStatement != null)
279 thenStatement.traverse(visitor, blockScope);
280 if (elseStatement != null)
281 elseStatement.traverse(visitor, blockScope);
283 visitor.endVisit(this, blockScope);