Added empty, foreach and isset keyword.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / Block.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.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.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18
19 public class Block extends Statement {
20
21         public Statement[] statements;
22
23         public int explicitDeclarations;
24
25         // the number of explicit declaration , used to create scope
26         public BlockScope scope;
27
28         public static final Block None = new Block(0);
29
30         public Block(int explicitDeclarations) {
31                 this.explicitDeclarations = explicitDeclarations;
32         }
33
34         public FlowInfo analyseCode(BlockScope currentScope,
35                         FlowContext flowContext, FlowInfo flowInfo) {
36
37                 // empty block
38                 if (statements == null)
39                         return flowInfo;
40                 boolean didAlreadyComplain = false;
41                 for (int i = 0, max = statements.length; i < max; i++) {
42                         Statement stat;
43                         if (!flowInfo.complainIfUnreachable(stat = statements[i], scope,
44                                         didAlreadyComplain)) {
45                                 flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
46                         } else {
47                                 didAlreadyComplain = true;
48                         }
49                 }
50                 return flowInfo;
51         }
52
53         public static final Block EmptyWith(int sourceStart, int sourceEnd) {
54
55                 // return an empty block which position is s and e
56                 Block bk = new Block(0);
57                 bk.sourceStart = sourceStart;
58                 bk.sourceEnd = sourceEnd;
59                 return bk;
60         }
61
62         /**
63          * Code generation for a block
64          */
65         // public void generateCode(BlockScope currentScope, CodeStream codeStream)
66         // {
67         //
68         // if ((bits & IsReachableMASK) == 0) {
69         // return;
70         // }
71         // int pc = codeStream.position;
72         // if (statements != null) {
73         // for (int i = 0, max = statements.length; i < max; i++) {
74         // statements[i].generateCode(scope, codeStream);
75         // }
76         // } // for local variable debug attributes
77         // if (scope != currentScope) { // was really associated with its own scope
78         // codeStream.exitUserScope(scope);
79         // }
80         // codeStream.recordPositionsFrom(pc, this.sourceStart);
81         // }
82         public boolean isEmptyBlock() {
83
84                 return statements == null;
85         }
86
87         public StringBuffer printBody(int indent, StringBuffer output) {
88
89                 if (this.statements == null)
90                         return output;
91                 for (int i = 0; i < statements.length; i++) {
92                         statements[i].printStatement(indent + 1, output);
93                         output.append('\n');
94                 }
95                 return output;
96         }
97
98         public StringBuffer printStatement(int indent, StringBuffer output) {
99
100                 printIndent(indent, output);
101                 output.append("{\n"); //$NON-NLS-1$
102                 printBody(indent, output);
103                 return printIndent(indent, output).append('}');
104         }
105
106         public void resolve(BlockScope upperScope) {
107
108                 if (statements != null) {
109                         scope = explicitDeclarations == 0 ? upperScope : new BlockScope(
110                                         upperScope, explicitDeclarations);
111                         int i = 0, length = statements.length;
112                         while (i < length)
113                                 statements[i++].resolve(scope);
114                 }
115         }
116
117         public void resolveUsing(BlockScope givenScope) {
118
119                 // this optimized resolve(...) is sent only on none empty blocks
120                 scope = givenScope;
121                 if (statements != null) {
122                         int i = 0, length = statements.length;
123                         while (i < length)
124                                 statements[i++].resolve(scope);
125                 }
126         }
127
128         public String toString(int tab) {
129
130                 String s = tabString(tab);
131                 if (this.statements == null) {
132                         s += "{\n"; //$NON-NLS-1$
133                         s += tabString(tab);
134                         s += "}"; //$NON-NLS-1$
135                         return s;
136                 }
137                 s += "{\n"; //$NON-NLS-1$
138                 s += this.toStringStatements(tab);
139                 s += tabString(tab);
140                 s += "}"; //$NON-NLS-1$
141                 return s;
142         }
143
144         public String toStringStatements(int tab) {
145
146                 if (this.statements == null)
147                         return ""; //$NON-NLS-1$
148                 StringBuffer buffer = new StringBuffer();
149                 for (int i = 0; i < statements.length; i++) {
150                         buffer.append(statements[i].toString(tab + 1));
151                         if (statements[i] instanceof Block) {
152                                 buffer.append("\n"); //$NON-NLS-1$
153                         } else {
154                                 buffer.append(";\n"); //$NON-NLS-1$
155                         }
156                 }
157                 ;
158                 return buffer.toString();
159         }
160
161         public void traverse(ASTVisitor visitor, BlockScope blockScope) {
162
163                 if (visitor.visit(this, blockScope)) {
164                         if (statements != null) {
165                                 int statementLength = statements.length;
166                                 for (int i = 0; i < statementLength; i++)
167                                         statements[i].traverse(visitor, scope);
168                         }
169                 }
170                 visitor.endVisit(this, blockScope);
171         }
172
173         /**
174          * Dispatch the call on its last statement.
175          */
176         public void branchChainTo(Label label) {
177                 if (this.statements != null) {
178                         this.statements[statements.length - 1].branchChainTo(label);
179                 }
180         }
181
182 }