1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class IfStatement extends Statement {
24 //this class represents the case of only one statement in
25 //either else and/or then branches.
27 public Expression condition;
28 public Statement thenStatement;
29 public Statement elseStatement;
33 // for local variables table attributes
34 int thenInitStateIndex = -1;
35 int elseInitStateIndex = -1;
36 int mergedInitStateIndex = -1;
40 Statement thenStatement,
44 this.condition = condition;
45 this.thenStatement = thenStatement;
52 Statement thenStatement,
53 Statement elseStatement,
57 this.condition = condition;
58 this.thenStatement = thenStatement;
59 this.elseStatement = elseStatement;
64 public FlowInfo analyseCode(
65 BlockScope currentScope,
66 FlowContext flowContext,
69 FlowInfo thenFlowInfo, elseFlowInfo;
71 // process the condition
72 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
74 // process the THEN part
75 if (thenStatement == null) {
76 thenFlowInfo = flowInfo.initsWhenTrue();
80 ((((cst = condition.constant) != NotAConstant)
81 && (cst.booleanValue() == false))
82 || (((cst = condition.conditionalConstant()) != NotAConstant)
83 && (cst.booleanValue() == false)))
84 ? (flowInfo.initsWhenTrue().copy().markAsFakeReachable(true))
85 : flowInfo.initsWhenTrue().copy();
86 // Save info for code gen
88 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
89 if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) {
91 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
94 // optimizing the jump around the ELSE part
95 thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable();
97 // process the ELSE part
98 if (elseStatement == null) {
99 elseFlowInfo = flowInfo.initsWhenFalse();
103 ((((cst = condition.constant) != NotAConstant) && (cst.booleanValue() == true))
104 || (((cst = condition.conditionalConstant()) != NotAConstant)
105 && (cst.booleanValue() == true)))
106 ? (flowInfo.initsWhenFalse().copy().markAsFakeReachable(true))
107 : flowInfo.initsWhenFalse().copy();
108 // Save info for code gen
110 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
111 if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) {
113 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
117 // merge THEN & ELSE initializations
119 if ((condition.constant != NotAConstant)
120 && (condition.constant.booleanValue() == true)) {
123 mergedInfo = elseFlowInfo.markAsFakeReachable(true);
124 mergedInitStateIndex =
125 currentScope.methodScope().recordInitializationStates(mergedInfo);
128 mergedInitStateIndex =
129 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
134 if ((condition.constant != NotAConstant)
135 && (condition.constant.booleanValue() == false)) {
136 if (elseFlowInfo.isDeadEnd()) {
137 mergedInfo = thenFlowInfo.markAsFakeReachable(true);
138 mergedInitStateIndex =
139 currentScope.methodScope().recordInitializationStates(mergedInfo);
142 mergedInitStateIndex =
143 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
148 mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
149 mergedInitStateIndex =
150 currentScope.methodScope().recordInitializationStates(mergedInfo);
157 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
158 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
160 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
162 if ((bits & IsReachableMASK) == 0) {
165 int pc = codeStream.position;
166 Label endifLabel = new Label(codeStream);
168 // optimizing the then/else part code gen
169 Constant cst, condCst;
170 boolean hasThenPart =
171 !((((cst = condition.constant) != NotAConstant)
172 && (cst.booleanValue() == false))
173 || (thenStatement == null)
174 || (thenStatement.isEmptyBlock())
175 || (((condCst = condition.conditionalConstant()) != NotAConstant)
176 && (condCst.booleanValue() == false)));
177 boolean hasElsePart =
178 !(((cst != NotAConstant) && (cst.booleanValue() == true))
179 || (elseStatement == null)
180 || (elseStatement.isEmptyBlock())
181 || (((condCst = condition.conditionalConstant()) != NotAConstant)
182 && (condCst.booleanValue() == true)));
186 // generate boolean condition
187 condition.generateOptimizedBoolean(
191 (falseLabel = new Label(codeStream)),
193 // May loose some local variable initializations : affecting the local variable attributes
194 if (thenInitStateIndex != -1) {
195 codeStream.removeNotDefinitelyAssignedVariables(
198 codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
200 // generate then statement
201 thenStatement.generateCode(currentScope, codeStream);
202 // jump around the else statement
203 if (hasElsePart && !thenExit) {
204 thenStatement.branchChainTo(endifLabel);
205 int position = codeStream.position;
206 codeStream.goto_(endifLabel);
207 codeStream.updateLastRecordedEndPC(position);
208 //goto is tagged as part of the thenAction block
213 // generate boolean condition
214 condition.generateOptimizedBoolean(
221 // generate condition side-effects
222 condition.generateCode(currentScope, codeStream, false);
223 codeStream.recordPositionsFrom(pc, this.sourceStart);
226 // generate else statement
228 // May loose some local variable initializations : affecting the local variable attributes
229 if (elseInitStateIndex != -1) {
230 codeStream.removeNotDefinitelyAssignedVariables(
233 codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
235 elseStatement.generateCode(currentScope, codeStream);
238 // May loose some local variable initializations : affecting the local variable attributes
239 if (mergedInitStateIndex != -1) {
240 codeStream.removeNotDefinitelyAssignedVariables(
242 mergedInitStateIndex);
244 codeStream.recordPositionsFrom(pc, this.sourceStart);
247 public void resolve(BlockScope scope) {
249 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
250 condition.implicitWidening(type, type);
251 if (thenStatement != null)
252 thenStatement.resolve(scope);
253 if (elseStatement != null)
254 elseStatement.resolve(scope);
257 public String toString(int tab) {
259 String inFront, s = tabString(tab);
261 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
262 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
263 if (elseStatement != null)
264 s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
268 public void traverse(
269 IAbstractSyntaxTreeVisitor visitor,
270 BlockScope blockScope) {
272 if (visitor.visit(this, blockScope)) {
273 condition.traverse(visitor, blockScope);
274 if (thenStatement != null)
275 thenStatement.traverse(visitor, blockScope);
276 if (elseStatement != null)
277 elseStatement.traverse(visitor, blockScope);
279 visitor.endVisit(this, blockScope);