+/*******************************************************************************
+ * 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 v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
package net.sourceforge.phpdt.internal.compiler.ast;
-import java.util.List;
-import java.util.ArrayList;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
-/**
- * A Block.
- * {
- * statements
- * }.
- * @author Matthieu Casanova
- */
public class Block extends Statement {
+
+ public Statement[] statements;
+ public int explicitDeclarations;
+ // the number of explicit declaration , used to create scope
+ public BlockScope scope;
+ public static final Block None = new Block(0);
+
+ public Block(int explicitDeclarations) {
+ this.explicitDeclarations = explicitDeclarations;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
- /** An array of statements inside the block. */
- public Statement[] statements;
-
- /**
- * Create a block.
- * @param statements the statements
- * @param sourceStart starting offset
- * @param sourceEnd ending offset
- */
- public Block(final Statement[] statements,
- final int sourceStart,
- final int sourceEnd) {
- super(sourceStart, sourceEnd);
- this.statements = statements;
- }
-
- /**
- * tell if the block is empty.
- * @return the block is empty if there are no statements in it
- */
- public boolean isEmptyBlock() {
- return statements == null;
- }
-
- /**
- * Return the block as String.
- * @param tab how many tabs
- * @return the string representation of the block
- */
- public String toString(final int tab) {
- final String s = AstNode.tabString(tab);
- final StringBuffer buff = new StringBuffer(s);
- buff.append("{\n"); //$NON-NLS-1$
- if (this.statements != null) {
- for (int i = 0; i < statements.length; i++) {
- buff.append(statements[i].toString(tab + 1)).append(";\n");//$NON-NLS-1$
- }
- }
- buff.append("}\n"); //$NON-NLS-1$
- return buff.toString();
- }
-
- /**
- * Get the variables from outside (parameters, globals ...)
- * @return the variables from outside
- */
- public List getOutsideVariable() {
- final ArrayList list = new ArrayList();
- for (int i = 0; i < statements.length; i++) {
- list.addAll(statements[i].getOutsideVariable());
- }
- return list;
- }
-
- /**
- * get the modified variables.
- * @return the variables from we change value
- */
- public List getModifiedVariable() {
- final ArrayList list = new ArrayList();
- for (int i = 0; i < statements.length; i++) {
- list.addAll(statements[i].getModifiedVariable());
- }
- return list;
- }
-
- /**
- * Get the variables used.
- * @return the variables used
- */
- public List getUsedVariable() {
- final ArrayList list = new ArrayList();
- for (int i = 0; i < statements.length; i++) {
- list.addAll(statements[i].getUsedVariable());
- }
- return list;
- }
+ // empty block
+ if (statements == null) return flowInfo;
+ boolean didAlreadyComplain = false;
+ for (int i = 0, max = statements.length; i < max; i++) {
+ Statement stat;
+ if (!flowInfo.complainIfUnreachable(stat = statements[i], scope, didAlreadyComplain)) {
+ flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+ } else {
+ didAlreadyComplain = true;
+ }
+ }
+ return flowInfo;
+ }
+
+ public static final Block EmptyWith(int sourceStart, int sourceEnd) {
+
+ //return an empty block which position is s and e
+ Block bk = new Block(0);
+ bk.sourceStart = sourceStart;
+ bk.sourceEnd = sourceEnd;
+ return bk;
+ }
+
+ /**
+ * Code generation for a block
+ */
+// public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+//
+// if ((bits & IsReachableMASK) == 0) {
+// return;
+// }
+// int pc = codeStream.position;
+// if (statements != null) {
+// for (int i = 0, max = statements.length; i < max; i++) {
+// statements[i].generateCode(scope, codeStream);
+// }
+// } // for local variable debug attributes
+// if (scope != currentScope) { // was really associated with its own scope
+// codeStream.exitUserScope(scope);
+// }
+// codeStream.recordPositionsFrom(pc, this.sourceStart);
+// }
+
+ public boolean isEmptyBlock() {
+
+ return statements == null;
+ }
+ public StringBuffer printBody(int indent, StringBuffer output) {
+
+ if (this.statements == null) return output;
+ for (int i = 0; i < statements.length; i++) {
+ statements[i].printStatement(indent + 1, output);
+ output.append('\n');
+ }
+ return output;
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ output.append("{\n"); //$NON-NLS-1$
+ printBody(indent, output);
+ return printIndent(indent, output).append('}');
+ }
+ public void resolve(BlockScope upperScope) {
+
+ if (statements != null) {
+ scope =
+ explicitDeclarations == 0
+ ? upperScope
+ : new BlockScope(upperScope, explicitDeclarations);
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+ }
+
+ public void resolveUsing(BlockScope givenScope) {
+
+ // this optimized resolve(...) is sent only on none empty blocks
+ scope = givenScope;
+ if (statements != null) {
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ if (this.statements == null) {
+ s += "{\n"; //$NON-NLS-1$
+ s += tabString(tab);
+ s += "}"; //$NON-NLS-1$
+ return s;
+ }
+ s += "{\n"; //$NON-NLS-1$
+ s += this.toStringStatements(tab);
+ s += tabString(tab);
+ s += "}"; //$NON-NLS-1$
+ return s;
+ }
+
+ public String toStringStatements(int tab) {
+
+ if (this.statements == null)
+ return ""; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < statements.length; i++) {
+ buffer.append(statements[i].toString(tab + 1));
+ if (statements[i] instanceof Block) {
+ buffer.append("\n"); //$NON-NLS-1$
+ } else {
+ buffer.append(";\n"); //$NON-NLS-1$
+ }
+ };
+ return buffer.toString();
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ if (statements != null) {
+ int statementLength = statements.length;
+ for (int i = 0; i < statementLength; i++)
+ statements[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ }
+
+ /**
+ * Dispatch the call on its last statement.
+ */
+ public void branchChainTo(Label label) {
+ if (this.statements != null) {
+ this.statements[statements.length - 1].branchChainTo(label);
+ }
+ }
+
}