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