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.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 public class IfStatement extends Statement {
21 //this class represents the case of only one statement in
22 //either else and/or then branches.
24 public Expression condition;
25 public Statement thenStatement;
26 public Statement elseStatement;
30 // for local variables table attributes
31 int thenInitStateIndex = -1;
32 int elseInitStateIndex = -1;
33 int mergedInitStateIndex = -1;
37 Statement thenStatement,
41 this.condition = condition;
42 this.thenStatement = thenStatement;
49 Statement thenStatement,
50 Statement elseStatement,
54 this.condition = condition;
55 this.thenStatement = thenStatement;
56 this.elseStatement = elseStatement;
61 public FlowInfo analyseCode(
62 BlockScope currentScope,
63 FlowContext flowContext,
66 FlowInfo thenFlowInfo, elseFlowInfo;
68 // process the condition
69 flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
71 // process the THEN part
72 if (thenStatement == null) {
73 thenFlowInfo = flowInfo.initsWhenTrue();
77 ((((cst = condition.constant) != NotAConstant)
78 && (cst.booleanValue() == false))
79 || (((cst = condition.conditionalConstant()) != NotAConstant)
80 && (cst.booleanValue() == false)))
81 ? (flowInfo.initsWhenTrue().copy().markAsFakeReachable(true))
82 : flowInfo.initsWhenTrue().copy();
83 // Save info for code gen
85 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
86 if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) {
88 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
91 // optimizing the jump around the ELSE part
92 thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable();
94 // process the ELSE part
95 if (elseStatement == null) {
96 elseFlowInfo = flowInfo.initsWhenFalse();
100 ((((cst = condition.constant) != NotAConstant) && (cst.booleanValue() == true))
101 || (((cst = condition.conditionalConstant()) != NotAConstant)
102 && (cst.booleanValue() == true)))
103 ? (flowInfo.initsWhenFalse().copy().markAsFakeReachable(true))
104 : flowInfo.initsWhenFalse().copy();
105 // Save info for code gen
107 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
108 if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) {
110 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
114 // merge THEN & ELSE initializations
116 if ((condition.constant != NotAConstant)
117 && (condition.constant.booleanValue() == true)) {
120 mergedInfo = elseFlowInfo.markAsFakeReachable(true);
121 mergedInitStateIndex =
122 currentScope.methodScope().recordInitializationStates(mergedInfo);
125 mergedInitStateIndex =
126 currentScope.methodScope().recordInitializationStates(thenFlowInfo);
131 if ((condition.constant != NotAConstant)
132 && (condition.constant.booleanValue() == false)) {
133 if (elseFlowInfo.isDeadEnd()) {
134 mergedInfo = thenFlowInfo.markAsFakeReachable(true);
135 mergedInitStateIndex =
136 currentScope.methodScope().recordInitializationStates(mergedInfo);
139 mergedInitStateIndex =
140 currentScope.methodScope().recordInitializationStates(elseFlowInfo);
145 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 ((bits & IsReachableMASK) == 0) {
162 int pc = codeStream.position;
163 Label endifLabel = new Label(codeStream);
165 // optimizing the then/else part code gen
166 Constant cst, condCst;
167 boolean hasThenPart =
168 !((((cst = condition.constant) != NotAConstant)
169 && (cst.booleanValue() == false))
170 || (thenStatement == null)
171 || (thenStatement.isEmptyBlock())
172 || (((condCst = condition.conditionalConstant()) != NotAConstant)
173 && (condCst.booleanValue() == false)));
174 boolean hasElsePart =
175 !(((cst != NotAConstant) && (cst.booleanValue() == true))
176 || (elseStatement == null)
177 || (elseStatement.isEmptyBlock())
178 || (((condCst = condition.conditionalConstant()) != NotAConstant)
179 && (condCst.booleanValue() == true)));
183 // generate boolean condition
184 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(
195 codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
197 // generate then statement
198 thenStatement.generateCode(currentScope, codeStream);
199 // jump around the else statement
200 if (hasElsePart && !thenExit) {
201 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
210 // generate boolean condition
211 condition.generateOptimizedBoolean(
218 // generate condition side-effects
219 condition.generateCode(currentScope, codeStream, false);
220 codeStream.recordPositionsFrom(pc, this.sourceStart);
223 // generate else statement
225 // May loose some local variable initializations : affecting the local variable attributes
226 if (elseInitStateIndex != -1) {
227 codeStream.removeNotDefinitelyAssignedVariables(
230 codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
232 elseStatement.generateCode(currentScope, codeStream);
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);
244 public void resolve(BlockScope scope) {
246 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
247 condition.implicitWidening(type, type);
248 if (thenStatement != null)
249 thenStatement.resolve(scope);
250 if (elseStatement != null)
251 elseStatement.resolve(scope);
254 public String toString(int tab) {
256 String inFront, s = tabString(tab);
258 s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
259 s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
260 if (elseStatement != null)
261 s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
265 public void traverse(
266 IAbstractSyntaxTreeVisitor visitor,
267 BlockScope blockScope) {
269 if (visitor.visit(this, blockScope)) {
270 condition.traverse(visitor, blockScope);
271 if (thenStatement != null)
272 thenStatement.traverse(visitor, blockScope);
273 if (elseStatement != null)
274 elseStatement.traverse(visitor, blockScope);
276 visitor.endVisit(this, blockScope);