Mercurial > hg > truffle
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 14628:a08b8694f556
Truffle: Node API changes
deprecate adoptChild, no longer needed in constructor
add Node#insert for inserting new nodes into the tree (previously adoptChild)
add Node#adoptChildren() helper method that adopts all (direct and indirect) children of a node, automatically called in TruffleRuntime#createCallTarget
author | Andreas Woess <andreas.woess@jku.at> |
---|---|
date | Wed, 19 Mar 2014 23:11:46 +0100 |
parents | 6189c1983cd3 |
children | ba52fbec5b6c |
comparison
equal
deleted
inserted
replaced
14627:46c020971d9c | 14628:a08b8694f556 |
---|---|
131 * node. | 131 * node. |
132 * | 132 * |
133 * @param newChildren the array of new children whose parent should be updated | 133 * @param newChildren the array of new children whose parent should be updated |
134 * @return the array of new children | 134 * @return the array of new children |
135 */ | 135 */ |
136 protected final <T extends Node> T[] adoptChildren(T[] newChildren) { | 136 @SuppressWarnings("static-method") |
137 if (newChildren != null) { | 137 @Deprecated |
138 for (T n : newChildren) { | 138 protected final <T extends Node> T[] adoptChildren(final T[] newChildren) { |
139 adoptChild(n); | |
140 } | |
141 } | |
142 return newChildren; | 139 return newChildren; |
143 } | 140 } |
144 | 141 |
145 /** | 142 /** |
146 * Method that updates the link to the parent in the specified new child node to this node. | 143 * Method that updates the link to the parent in the specified new child node to this node. |
147 * | 144 * |
148 * @param newChild the new child whose parent should be updated | 145 * @param newChild the new child whose parent should be updated |
149 * @return the new child | 146 * @return the new child |
150 */ | 147 */ |
151 protected final <T extends Node> T adoptChild(T newChild) { | 148 @SuppressWarnings("static-method") |
152 if (newChild != null) { | 149 @Deprecated |
153 if (newChild == this) { | 150 protected final <T extends Node> T adoptChild(final T newChild) { |
154 throw new IllegalStateException("The parent of a node can never be the node itself."); | |
155 } | |
156 ((Node) newChild).parent = this; | |
157 } | |
158 return newChild; | 151 return newChild; |
152 } | |
153 | |
154 /** | |
155 * Method that updates the link to the parent in the array of specified new child nodes to this | |
156 * node. | |
157 * | |
158 * @param newChildren the array of new children whose parent should be updated | |
159 * @return the array of new children | |
160 */ | |
161 protected final <T extends Node> T[] insert(final T[] newChildren) { | |
162 CompilerDirectives.transferToInterpreterAndInvalidate(); | |
163 assert newChildren != null; | |
164 for (Node newChild : newChildren) { | |
165 adoptHelper(newChild); | |
166 } | |
167 return newChildren; | |
168 } | |
169 | |
170 /** | |
171 * Method that updates the link to the parent in the specified new child node to this node. | |
172 * | |
173 * @param newChild the new child whose parent should be updated | |
174 * @return the new child | |
175 */ | |
176 protected final <T extends Node> T insert(final T newChild) { | |
177 CompilerDirectives.transferToInterpreterAndInvalidate(); | |
178 assert newChild != null; | |
179 adoptHelper(newChild); | |
180 return newChild; | |
181 } | |
182 | |
183 public final void adoptChildren() { | |
184 CompilerDirectives.transferToInterpreterAndInvalidate(); | |
185 adoptHelper(); | |
186 } | |
187 | |
188 private void adoptHelper(final Node newChild) { | |
189 assert newChild != null; | |
190 if (newChild == this) { | |
191 throw new IllegalStateException("The parent of a node can never be the node itself."); | |
192 } | |
193 newChild.parent = this; | |
194 newChild.adoptHelper(); | |
195 } | |
196 | |
197 private void adoptHelper() { | |
198 Iterable<Node> children = this.getChildren(); | |
199 for (Node child : children) { | |
200 if (child != null && child.getParent() != this) { | |
201 this.adoptHelper(child); | |
202 } | |
203 } | |
204 } | |
205 | |
206 private void adoptUnadoptedHelper(final Node newChild) { | |
207 assert newChild != null; | |
208 if (newChild == this) { | |
209 throw new IllegalStateException("The parent of a node can never be the node itself."); | |
210 } | |
211 newChild.parent = this; | |
212 newChild.adoptUnadoptedHelper(); | |
213 } | |
214 | |
215 private void adoptUnadoptedHelper() { | |
216 Iterable<Node> children = this.getChildren(); | |
217 for (Node child : children) { | |
218 if (child != null && child.getParent() == null) { | |
219 this.adoptUnadoptedHelper(child); | |
220 } | |
221 } | |
159 } | 222 } |
160 | 223 |
161 /** | 224 /** |
162 * Returns properties of this node interesting for debugging and can be overwritten by | 225 * Returns properties of this node interesting for debugging and can be overwritten by |
163 * subclasses to add their own custom properties. | 226 * subclasses to add their own custom properties. |
184 * | 247 * |
185 * @param newNode the new node that is the replacement | 248 * @param newNode the new node that is the replacement |
186 * @param reason a description of the reason for the replacement | 249 * @param reason a description of the reason for the replacement |
187 * @return the new node | 250 * @return the new node |
188 */ | 251 */ |
189 public final <T extends Node> T replace(T newNode, CharSequence reason) { | 252 public final <T extends Node> T replace(final T newNode, final CharSequence reason) { |
190 CompilerDirectives.transferToInterpreterAndInvalidate(); | 253 CompilerDirectives.transferToInterpreterAndInvalidate(); |
254 replaceHelper(newNode, reason); | |
255 return newNode; | |
256 } | |
257 | |
258 /** | |
259 * Replaces this node with another node. If there is a source section (see | |
260 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node. | |
261 * | |
262 * @param newNode the new node that is the replacement | |
263 * @return the new node | |
264 */ | |
265 public final <T extends Node> T replace(T newNode) { | |
266 return replace(newNode, ""); | |
267 } | |
268 | |
269 private void replaceHelper(Node newNode, CharSequence reason) { | |
270 CompilerAsserts.neverPartOfCompilation(); | |
191 if (this.getParent() == null) { | 271 if (this.getParent() == null) { |
192 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); | 272 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); |
193 } | 273 } |
194 if (sourceSection != null && newNode.getSourceSection() == null) { | 274 if (sourceSection != null && newNode.getSourceSection() == null) { |
195 // Pass on the source section to the new node. | 275 // Pass on the source section to the new node. |
196 newNode.assignSourceSection(sourceSection); | 276 newNode.assignSourceSection(sourceSection); |
197 } | 277 } |
278 // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode() | |
279 // will always find the root node | |
280 newNode.parent = this.parent; | |
281 if (NodeUtil.replaceChild(this.parent, this, newNode)) { | |
282 this.parent.adoptHelper(newNode); | |
283 } else { | |
284 this.parent.adoptUnadoptedHelper(newNode); | |
285 } | |
286 reportReplace(this, newNode, reason); | |
198 onReplace(newNode, reason); | 287 onReplace(newNode, reason); |
199 ((Node) newNode).parent = this.parent; | |
200 if (!NodeUtil.replaceChild(this.parent, this, newNode)) { | |
201 fixupTree(); | |
202 } | |
203 reportReplace(this, newNode, reason); | |
204 return newNode; | |
205 } | |
206 | |
207 /** | |
208 * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references. | |
209 * | |
210 * This is a rather expensive operation but rare to occur. | |
211 */ | |
212 private void fixupTree() { | |
213 Node rootNode = getRootNode(); | |
214 if (rootNode == null) { | |
215 throw new UnsupportedOperationException("Tree does not have a root node."); | |
216 } | |
217 int fixCount = rootNode.fixupChildren(); | |
218 assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?"; | |
219 // if nothing had to be fixed, rewrite failed due to node not being a proper child. | |
220 } | |
221 | |
222 private int fixupChildren() { | |
223 int fixCount = 0; | |
224 for (Node child : getChildren()) { | |
225 if (child != null) { | |
226 if (child.parent != this) { | |
227 child.parent = this; | |
228 fixCount++; | |
229 } | |
230 fixCount += child.fixupChildren(); | |
231 } | |
232 } | |
233 return fixCount; | |
234 } | |
235 | |
236 /** | |
237 * Replaces this node with another node. If there is a source section (see | |
238 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node. | |
239 * | |
240 * @param newNode the new node that is the replacement | |
241 * @return the new node | |
242 */ | |
243 public final <T extends Node> T replace(T newNode) { | |
244 return replace(newNode, ""); | |
245 } | 288 } |
246 | 289 |
247 /** | 290 /** |
248 * Checks if this node is properly adopted by a parent and can be replaced. | 291 * Checks if this node is properly adopted by a parent and can be replaced. |
249 * | 292 * |