d52f2c7ebef035bc0bc74ffb8e32e3330edaf135
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / Block.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
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.lookup.BlockScope;
19
20 public class Block extends Statement {
21         
22         public Statement[] statements;
23         public int explicitDeclarations;
24         // the number of explicit declaration , used to create scope
25         public BlockScope scope;
26         public static final Block None = new Block(0);
27         
28         public Block(int explicitDeclarations) {
29                 this.explicitDeclarations = explicitDeclarations;
30         }
31         
32         public FlowInfo analyseCode(
33                 BlockScope currentScope,
34                 FlowContext flowContext,
35                 FlowInfo flowInfo) {
36
37                 // empty block
38                 if (statements == null)
39                         return flowInfo;
40                 for (int i = 0, max = statements.length; i < max; i++) {
41                         Statement stat;
42                         if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
43                                 flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
44                         }
45                 }
46                 return flowInfo;
47         }
48
49         public static final Block EmptyWith(int sourceStart, int sourceEnd) {
50
51                 //return an empty block which position is s and e
52                 Block bk = new Block(0);
53                 bk.sourceStart = sourceStart;
54                 bk.sourceEnd = sourceEnd;
55                 return bk;
56         }
57
58         /**
59          * Code generation for a block
60          */
61         public void generateCode(BlockScope currentScope, CodeStream codeStream) {
62
63                 if ((bits & IsReachableMASK) == 0) {
64                         return;
65                 }
66                 int pc = codeStream.position;
67                 if (statements != null) {
68                         for (int i = 0, max = statements.length; i < max; i++) {
69                                 statements[i].generateCode(scope, codeStream);
70                         }
71                 } // for local variable debug attributes
72                 if (scope != currentScope) { // was really associated with its own scope
73                         codeStream.exitUserScope(scope);
74                 }
75                 codeStream.recordPositionsFrom(pc, this.sourceStart);
76         }
77
78         public boolean isEmptyBlock() {
79
80                 return statements == null;
81         }
82
83         public void resolve(BlockScope upperScope) {
84
85                 if (statements != null) {
86                         scope =
87                                 explicitDeclarations == 0
88                                         ? upperScope
89                                         : new BlockScope(upperScope, explicitDeclarations);
90                         int i = 0, length = statements.length;
91                         while (i < length)
92                                 statements[i++].resolve(scope);
93                 }
94         }
95
96         public void resolveUsing(BlockScope givenScope) {
97
98                 // this optimized resolve(...) is sent only on none empty blocks
99                 scope = givenScope;
100                 if (statements != null) {
101                         int i = 0, length = statements.length;
102                         while (i < length)
103                                 statements[i++].resolve(scope);
104                 }
105         }
106
107         public String toString(int tab) {
108
109                 String s = tabString(tab);
110                 if (this.statements == null) {
111                         s += "{\n"; //$NON-NLS-1$
112                         s += tabString(tab);
113                         s += "}"; //$NON-NLS-1$
114                         return s;
115                 }
116                 s += "{\n"; //$NON-NLS-1$
117                 s += this.toStringStatements(tab);
118                 s += tabString(tab);
119                 s += "}"; //$NON-NLS-1$
120                 return s;
121         }
122
123         public String toStringStatements(int tab) {
124
125                 if (this.statements == null)
126                         return ""; //$NON-NLS-1$
127                 StringBuffer buffer = new StringBuffer();
128                 for (int i = 0; i < statements.length; i++) {
129                         buffer.append(statements[i].toString(tab + 1));
130                         if (statements[i] instanceof Block) {
131                                 buffer.append("\n"); //$NON-NLS-1$
132                         } else {
133                                 buffer.append(";\n"); //$NON-NLS-1$
134                         }
135                 };
136                 return buffer.toString();
137         }
138
139         public void traverse(
140                 IAbstractSyntaxTreeVisitor visitor,
141                 BlockScope blockScope) {
142
143                 if (visitor.visit(this, blockScope)) {
144                         if (statements != null) {
145                                 int statementLength = statements.length;
146                                 for (int i = 0; i < statementLength; i++)
147                                         statements[i].traverse(visitor, scope);
148                         }
149                 }
150                 visitor.endVisit(this, blockScope);
151         }
152         
153         /**
154          * Dispatch the call on its last statement.
155          */
156         public void branchChainTo(Label label) {
157                  if (this.statements != null) {
158                         this.statements[statements.length - 1].branchChainTo(label);
159                  }
160         }
161         
162 }