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 index 182f72a..7959ba7 100644 --- 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 @@ -1,18 +1,16 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.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.codegen.CodeStream; -import net.sourceforge.phpdt.internal.compiler.codegen.Label; +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; import net.sourceforge.phpdt.internal.compiler.impl.Constant; @@ -27,8 +25,11 @@ public class IfStatement extends Statement { public Expression condition; public Statement thenStatement; public Statement elseStatement; - + public Expression[] elseifConditions; + public Statement[] elseifStatements; + public boolean checkUnreachable; boolean thenExit; + // for local variables table attributes int thenInitStateIndex = -1; @@ -45,6 +46,7 @@ public class IfStatement extends Statement { this.thenStatement = thenStatement; sourceStart = s; sourceEnd = e; + checkUnreachable = true; } public IfStatement( @@ -59,6 +61,7 @@ public class IfStatement extends Statement { this.elseStatement = elseStatement; sourceEnd = e; sourceStart = s; + checkUnreachable = true; } public FlowInfo analyseCode( @@ -66,86 +69,84 @@ public class IfStatement extends Statement { FlowContext flowContext, FlowInfo flowInfo) { - FlowInfo thenFlowInfo, elseFlowInfo; - // process the condition flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo); + Constant cst = this.condition.optimizedBooleanConstant(); + boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true; + boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false; + // 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(); + FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy(); + if (isConditionOptimizedFalse) { + thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); + } + if (this.thenStatement != null) { // Save info for code gen thenInitStateIndex = currentScope.methodScope().recordInitializationStates(thenFlowInfo); - if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) { + if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) { thenFlowInfo = thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo); } }; // optimizing the jump around the ELSE part - thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable(); + this.thenExit = !thenFlowInfo.isReachable(); // 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(); + FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy(); + if (isConditionOptimizedTrue) { + elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); + } + if (this.elseStatement != null) { // Save info for code gen elseInitStateIndex = currentScope.methodScope().recordInitializationStates(elseFlowInfo); - if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) { + if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) { elseFlowInfo = elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); } } + boolean elseExit = !elseFlowInfo.isReachable(); + // 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; +// if (isConditionOptimizedTrue){ +// if (!this.thenExit) { +// mergedInfo = thenFlowInfo; +// } else { +// mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); +// } +// +// } else if (isConditionOptimizedFalse) { +// if (!elseExit) { +// mergedInfo = elseFlowInfo; +// } else { +// mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); +// } +// +// } else { +// mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits()); +// } + if (isConditionOptimizedTrue){ + if (!this.thenExit) { + mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo); } else { - mergedInitStateIndex = - currentScope.methodScope().recordInitializationStates(thenFlowInfo); - return thenFlowInfo; + mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); } - } 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; - } + + } else if (isConditionOptimizedFalse) { + if (!elseExit) { + mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo); + } else { + mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); } + + } else { + mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits()); } - mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits()); + mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); return mergedInfo; @@ -154,96 +155,104 @@ public class IfStatement extends Statement { /** * If code generation * - * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope - * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope + * @param codeStream net.sourceforge.phpdt.internal.compiler.codegen.CodeStream */ - public void generateCode(BlockScope currentScope, CodeStream codeStream) { +// public void generateCode(BlockScope currentScope, CodeStream codeStream) { +// +// if ((this.bits & IsReachableMASK) == 0) { +// return; +// } +// int pc = codeStream.position; +// Label endifLabel = new Label(codeStream); +// +// // optimizing the then/else part code gen +// Constant cst; +// boolean hasThenPart = +// !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant +// && cst.booleanValue() == false) +// || this.thenStatement == null +// || this.thenStatement.isEmptyBlock()); +// boolean hasElsePart = +// !((cst != NotAConstant && cst.booleanValue() == true) +// || this.elseStatement == null +// || this.elseStatement.isEmptyBlock()); +// +// if (hasThenPart) { +// Label falseLabel; +// // generate boolean condition +// this.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 +// this.thenStatement.generateCode(currentScope, codeStream); +// // jump around the else statement +// if (hasElsePart && !thenExit) { +// this.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 +// this.condition.generateOptimizedBoolean( +// currentScope, +// codeStream, +// endifLabel, +// null, +// true); +// } else { +// // generate condition side-effects +// this.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); +// } +// this.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 StringBuffer printStatement(int indent, StringBuffer output) { - if ((bits & IsReachableMASK) == 0) { - return; + printIndent(indent, output).append("if ("); //$NON-NLS-1$ + condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$ + thenStatement.printStatement(indent + 2, output); + if (elseStatement != null) { + output.append('\n'); + printIndent(indent, output); + output.append("else\n"); //$NON-NLS-1$ + elseStatement.printStatement(indent + 2, output); } - 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); + return output; } - public void resolve(BlockScope scope) { TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding); @@ -266,7 +275,7 @@ public class IfStatement extends Statement { } public void traverse( - IAbstractSyntaxTreeVisitor visitor, + ASTVisitor visitor, BlockScope blockScope) { if (visitor.visit(this, blockScope)) { @@ -278,4 +287,4 @@ public class IfStatement extends Statement { } visitor.endVisit(this, blockScope); } -} \ No newline at end of file +}