128 public boolean isGlobalScope() { |
128 public boolean isGlobalScope() { |
129 return getFlag(IS_GLOBAL_SCOPE); |
129 return getFlag(IS_GLOBAL_SCOPE); |
130 } |
130 } |
131 |
131 |
132 /** |
132 /** |
133 * Clear the symbols in the block. |
133 * Returns true if this block defines any symbols. |
134 * TODO: make this immutable. |
134 * @return true if this block defines any symbols. |
135 */ |
135 */ |
136 public void clearSymbols() { |
136 public boolean hasSymbols() { |
137 symbols.clear(); |
137 return !symbols.isEmpty(); |
|
138 } |
|
139 |
|
140 /** |
|
141 * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are |
|
142 * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the |
|
143 * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols. |
|
144 * Those should be updated separately as this method is meant to be used as part of such an update pass. |
|
145 * @param lc the current lexical context |
|
146 * @param replacements the map of symbol replacements |
|
147 * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol |
|
148 * table. |
|
149 */ |
|
150 public Block replaceSymbols(final LexicalContext lc, final Map<Symbol, Symbol> replacements) { |
|
151 if (symbols.isEmpty()) { |
|
152 return this; |
|
153 } |
|
154 final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols); |
|
155 for (final Map.Entry<String, Symbol> entry: newSymbols.entrySet()) { |
|
156 final Symbol newSymbol = replacements.get(entry.getValue()); |
|
157 assert newSymbol != null : "Missing replacement for " + entry.getKey(); |
|
158 entry.setValue(newSymbol); |
|
159 } |
|
160 return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion)); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Returns a copy of this block with a shallow copy of the symbol table. |
|
165 * @return a copy of this block with a shallow copy of the symbol table. |
|
166 */ |
|
167 public Block copyWithNewSymbols() { |
|
168 return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion); |
138 } |
169 } |
139 |
170 |
140 @Override |
171 @Override |
141 public Node ensureUniqueLabels(final LexicalContext lc) { |
172 public Node ensureUniqueLabels(final LexicalContext lc) { |
142 return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); |
173 return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); |
160 /** |
191 /** |
161 * Get a copy of the list for all the symbols defined in this block |
192 * Get a copy of the list for all the symbols defined in this block |
162 * @return symbol iterator |
193 * @return symbol iterator |
163 */ |
194 */ |
164 public List<Symbol> getSymbols() { |
195 public List<Symbol> getSymbols() { |
165 return Collections.unmodifiableList(new ArrayList<>(symbols.values())); |
196 return symbols.isEmpty() ? Collections.<Symbol>emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values())); |
166 } |
197 } |
167 |
198 |
168 /** |
199 /** |
169 * Retrieves an existing symbol defined in the current block. |
200 * Retrieves an existing symbol defined in the current block. |
170 * @param name the name of the symbol |
201 * @param name the name of the symbol |
324 } |
355 } |
325 |
356 |
326 /** |
357 /** |
327 * Add or overwrite an existing symbol in the block |
358 * Add or overwrite an existing symbol in the block |
328 * |
359 * |
329 * @param lc get lexical context |
|
330 * @param symbol symbol |
360 * @param symbol symbol |
331 */ |
361 */ |
332 public void putSymbol(final LexicalContext lc, final Symbol symbol) { |
362 public void putSymbol(final Symbol symbol) { |
333 symbols.put(symbol.getName(), symbol); |
363 symbols.put(symbol.getName(), symbol); |
334 } |
364 } |
335 |
365 |
336 /** |
366 /** |
337 * Check whether scope is necessary for this Block |
367 * Check whether scope is necessary for this Block |