X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/IfStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/IfStatement.java new file mode 100644 index 0000000..2c11637 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/IfStatement.java @@ -0,0 +1,278 @@ +/******************************************************************************* + * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ +package net.sourceforge.phpdt.internal.compiler.ast; + +import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; +import net.sourceforge.phpdt.internal.compiler.impl.*; +import net.sourceforge.phpdt.internal.compiler.codegen.*; +import net.sourceforge.phpdt.internal.compiler.flow.*; +import net.sourceforge.phpdt.internal.compiler.lookup.*; + +public class IfStatement extends Statement { + + //this class represents the case of only one statement in + //either else and/or then branches. + + public Expression condition; + public Statement thenStatement; + public Statement elseStatement; + + boolean thenExit; + + // for local variables table attributes + int thenInitStateIndex = -1; + int elseInitStateIndex = -1; + int mergedInitStateIndex = -1; + + public IfStatement( + Expression condition, + Statement thenStatement, + int s, + int e) { + + this.condition = condition; + this.thenStatement = thenStatement; + sourceStart = s; + sourceEnd = e; + } + + public IfStatement( + Expression condition, + Statement thenStatement, + Statement elseStatement, + int s, + int e) { + + this.condition = condition; + this.thenStatement = thenStatement; + this.elseStatement = elseStatement; + sourceEnd = e; + sourceStart = s; + } + + public FlowInfo analyseCode( + BlockScope currentScope, + FlowContext flowContext, + FlowInfo flowInfo) { + + FlowInfo thenFlowInfo, elseFlowInfo; + + // process the condition + flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo); + + // process the THEN part + if (thenStatement == null) { + thenFlowInfo = flowInfo.initsWhenTrue(); + } else { + Constant cst; + thenFlowInfo = + ((((cst = condition.constant) != NotAConstant) + && (cst.booleanValue() == false)) + || (((cst = condition.conditionalConstant()) != NotAConstant) + && (cst.booleanValue() == false))) + ? (flowInfo.initsWhenTrue().copy().markAsFakeReachable(true)) + : flowInfo.initsWhenTrue().copy(); + // Save info for code gen + thenInitStateIndex = + currentScope.methodScope().recordInitializationStates(thenFlowInfo); + if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) { + thenFlowInfo = + thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo); + } + }; + // optimizing the jump around the ELSE part + thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable(); + + // process the ELSE part + if (elseStatement == null) { + elseFlowInfo = flowInfo.initsWhenFalse(); + } else { + Constant cst; + elseFlowInfo = + ((((cst = condition.constant) != NotAConstant) && (cst.booleanValue() == true)) + || (((cst = condition.conditionalConstant()) != NotAConstant) + && (cst.booleanValue() == true))) + ? (flowInfo.initsWhenFalse().copy().markAsFakeReachable(true)) + : flowInfo.initsWhenFalse().copy(); + // Save info for code gen + elseInitStateIndex = + currentScope.methodScope().recordInitializationStates(elseFlowInfo); + if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) { + elseFlowInfo = + elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); + } + } + + // merge THEN & ELSE initializations + FlowInfo mergedInfo; + if ((condition.constant != NotAConstant) + && (condition.constant.booleanValue() == true)) { + // IF (TRUE) + if (thenExit) { + mergedInfo = elseFlowInfo.markAsFakeReachable(true); + mergedInitStateIndex = + currentScope.methodScope().recordInitializationStates(mergedInfo); + return mergedInfo; + } else { + mergedInitStateIndex = + currentScope.methodScope().recordInitializationStates(thenFlowInfo); + return thenFlowInfo; + } + } else { + // IF (FALSE) + if ((condition.constant != NotAConstant) + && (condition.constant.booleanValue() == false)) { + if (elseFlowInfo.isDeadEnd()) { + mergedInfo = thenFlowInfo.markAsFakeReachable(true); + mergedInitStateIndex = + currentScope.methodScope().recordInitializationStates(mergedInfo); + return mergedInfo; + } else { + mergedInitStateIndex = + currentScope.methodScope().recordInitializationStates(elseFlowInfo); + return elseFlowInfo; + } + } + } + mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits()); + mergedInitStateIndex = + currentScope.methodScope().recordInitializationStates(mergedInfo); + return mergedInfo; + } + + /** + * If code generation + * + * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope + * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + */ + public void generateCode(BlockScope currentScope, CodeStream codeStream) { + + if ((bits & IsReachableMASK) == 0) { + return; + } + int pc = codeStream.position; + Label endifLabel = new Label(codeStream); + + // optimizing the then/else part code gen + Constant cst, condCst; + boolean hasThenPart = + !((((cst = condition.constant) != NotAConstant) + && (cst.booleanValue() == false)) + || (thenStatement == null) + || (thenStatement.isEmptyBlock()) + || (((condCst = condition.conditionalConstant()) != NotAConstant) + && (condCst.booleanValue() == false))); + boolean hasElsePart = + !(((cst != NotAConstant) && (cst.booleanValue() == true)) + || (elseStatement == null) + || (elseStatement.isEmptyBlock()) + || (((condCst = condition.conditionalConstant()) != NotAConstant) + && (condCst.booleanValue() == true))); + + if (hasThenPart) { + Label falseLabel; + // generate boolean condition + condition.generateOptimizedBoolean( + currentScope, + codeStream, + null, + (falseLabel = new Label(codeStream)), + true); + // May loose some local variable initializations : affecting the local variable attributes + if (thenInitStateIndex != -1) { + codeStream.removeNotDefinitelyAssignedVariables( + currentScope, + thenInitStateIndex); + codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex); + } + // generate then statement + thenStatement.generateCode(currentScope, codeStream); + // jump around the else statement + if (hasElsePart && !thenExit) { + thenStatement.branchChainTo(endifLabel); + int position = codeStream.position; + codeStream.goto_(endifLabel); + codeStream.updateLastRecordedEndPC(position); + //goto is tagged as part of the thenAction block + } + falseLabel.place(); + } else { + if (hasElsePart) { + // generate boolean condition + condition.generateOptimizedBoolean( + currentScope, + codeStream, + endifLabel, + null, + true); + } else { + // generate condition side-effects + condition.generateCode(currentScope, codeStream, false); + codeStream.recordPositionsFrom(pc, this.sourceStart); + } + } + // generate else statement + if (hasElsePart) { + // May loose some local variable initializations : affecting the local variable attributes + if (elseInitStateIndex != -1) { + codeStream.removeNotDefinitelyAssignedVariables( + currentScope, + elseInitStateIndex); + codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex); + } + elseStatement.generateCode(currentScope, codeStream); + } + endifLabel.place(); + // May loose some local variable initializations : affecting the local variable attributes + if (mergedInitStateIndex != -1) { + codeStream.removeNotDefinitelyAssignedVariables( + currentScope, + mergedInitStateIndex); + } + codeStream.recordPositionsFrom(pc, this.sourceStart); + } + + public void resolve(BlockScope scope) { + + TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding); + condition.implicitWidening(type, type); + if (thenStatement != null) + thenStatement.resolve(scope); + if (elseStatement != null) + elseStatement.resolve(scope); + } + + public String toString(int tab) { + + String inFront, s = tabString(tab); + inFront = s; + s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$ + s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$ + if (elseStatement != null) + s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$ + return s; + } + + public void traverse( + IAbstractSyntaxTreeVisitor visitor, + BlockScope blockScope) { + + if (visitor.visit(this, blockScope)) { + condition.traverse(visitor, blockScope); + if (thenStatement != null) + thenStatement.traverse(visitor, blockScope); + if (elseStatement != null) + elseStatement.traverse(visitor, blockScope); + } + visitor.endVisit(this, blockScope); + } +} \ No newline at end of file