1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.ast;
47
48 import java.util.ArrayList;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.List;
52 import java.util.Set;
53
54 /***
55 * Represents a variable scope. This is primarily used to determine variable sharing
56 * across method and closure boundaries.
57 *
58 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
59 * @version $Revision: 1.5 $
60 */
61 public class VariableScope {
62 static int i = 0;
63 private Set declaredVariables = new HashSet();
64 private Set referencedVariables = new HashSet();
65
66 /***
67 * br contain vars really declared and defined in the current scope.
68 * to be filler later by comparing with parent scope all the ancestors.
69 */
70 private Set varsDeclaredHere = null;
71
72
73
74
75
76
77
78 private VariableScope parent;
79 private List children = new ArrayList();
80 String name = null;
81
82 public VariableScope() {
83 name = String.valueOf(i++);
84 }
85
86 public VariableScope(VariableScope parent) {
87 this.parent = parent;
88 parent.children.add(this);
89 name = String.valueOf(i);
90 }
91
92 public Set getDeclaredVariables() {
93 return declaredVariables;
94 }
95
96 public Set getReferencedVariables() {
97 return referencedVariables;
98 }
99
100 /***
101 * @return all the child scopes
102 */
103 public List getChildren() {
104 return children;
105 }
106
107 /***
108 * Creates a composite variable scope combining all the variable references
109 * and declarations from all the child scopes not including this scope
110 *
111 * @return
112 */
113 public VariableScope createCompositeChildScope() {
114 VariableScope answer = new VariableScope();
115 for (Iterator iter = children.iterator(); iter.hasNext(); ) {
116 answer.appendRecursive((VariableScope) iter.next());
117 }
118 answer.parent = this;
119 return answer;
120 }
121
122 /***
123 * Creates a scope including this scope and all nested scopes combined together
124 *
125 * @return
126 */
127 public VariableScope createRecursiveChildScope() {
128 VariableScope answer = createCompositeChildScope();
129 answer.referencedVariables.addAll(referencedVariables);
130 answer.declaredVariables.addAll(declaredVariables);
131 return answer;
132 }
133
134 /***
135 * Creates a scope including this scope and all parent scopes combined together
136 *
137 * @return
138 */
139 public VariableScope createRecursiveParentScope() {
140 VariableScope answer = new VariableScope();
141 VariableScope node = this;
142 do {
143 answer.append(node);
144 node = node.parent;
145 }
146 while (node != null);
147 return answer;
148 }
149
150 /***
151 * Appends all of the references and declarations from the given scope
152 * to this one
153 *
154 * @param scope
155 */
156 protected void append(VariableScope scope) {
157 referencedVariables.addAll(scope.referencedVariables);
158 declaredVariables.addAll(scope.declaredVariables);
159 }
160
161 /***
162 * Appends all of the references and declarations from the given scope
163 * and all its children to this one
164 *
165 * @param scope
166 */
167 protected void appendRecursive(VariableScope scope) {
168 append(scope);
169
170
171 for (Iterator iter = scope.children.iterator(); iter.hasNext(); ) {
172 appendRecursive((VariableScope) iter.next());
173 }
174 }
175
176
177
178
179
180
181
182
183 public void computeRealDeclares() {
184 if (this.varsDeclaredHere == null) this.varsDeclaredHere = new HashSet();
185 Set decls = this.declaredVariables;
186 for (Iterator iter = decls.iterator(); iter.hasNext();) {
187 String var = (String) iter.next();
188
189 if (!createRecursiveParentScope().getDeclaredVariables().contains(var)) {
190 this.varsDeclaredHere.add(var);
191 }
192 }
193 }
194 /***
195 * @return Returns the varsDeclaredHere.
196 */
197 public Set getVarsDeclaredHere() {
198 if (this.varsDeclaredHere == null) computeRealDeclares();
199 return varsDeclaredHere;
200 }
201 /***
202 * @param varsDeclaredHere The varsDeclaredHere to set.
203 */
204 public void setVarsDeclaredHere(Set varsDeclaredHere) {
205 this.varsDeclaredHere = varsDeclaredHere;
206 }
207
208 public VariableScope getParent() {
209 return parent;
210 }
211 }