Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 7267:a4b84ba6dc2e
Introduction of the Truffle API for efficient implementation of dynamic languages on top of the Graal VM. New projects com.oracle.truffle.api for the API definition and com.oracle.truffle.api.test for API tests and documentation.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Tue, 18 Dec 2012 15:33:55 +0100 |
parents | |
children | 5e3d1a68664e |
comparison
equal
deleted
inserted
replaced
7259:494d99e07614 | 7267:a4b84ba6dc2e |
---|---|
1 /* | |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.api.nodes; | |
24 | |
25 import java.lang.annotation.*; | |
26 import java.util.*; | |
27 | |
28 /** | |
29 * Abstract base class for all Truffle nodes. | |
30 */ | |
31 public abstract class Node implements Cloneable { | |
32 | |
33 /** | |
34 * Utility constant representing an empty node array. | |
35 */ | |
36 public static final Node[] EMPTY_ARRAY = new Node[0]; | |
37 | |
38 private Node parent; | |
39 | |
40 /** | |
41 * Marks array fields that are children of this node. | |
42 */ | |
43 @Retention(RetentionPolicy.RUNTIME) | |
44 @Target({ElementType.FIELD}) | |
45 public @interface Children { | |
46 } | |
47 | |
48 /** | |
49 * Marks fields that represent child nodes of this node. | |
50 */ | |
51 @Retention(RetentionPolicy.RUNTIME) | |
52 @Target({ElementType.FIELD}) | |
53 public @interface Child { | |
54 } | |
55 | |
56 /** | |
57 * Method that updates the link to the parent in the array of specified new child nodes to this node. | |
58 * | |
59 * @param newChildren the array of new children whose parent should be updated | |
60 * @return the array of new children | |
61 */ | |
62 protected final <T extends Node> T[] adoptChildren(T[] newChildren) { | |
63 if (newChildren != null) { | |
64 for (T n : newChildren) { | |
65 adoptChild(n); | |
66 } | |
67 } | |
68 return newChildren; | |
69 } | |
70 | |
71 /** | |
72 * Method that updates the link to the parent in the specified new child node to this node. | |
73 * | |
74 * @param newChild the new child whose parent should be updated | |
75 * @return the new child | |
76 */ | |
77 protected final <T extends Node> T adoptChild(T newChild) { | |
78 if (newChild != null) { | |
79 ((Node) newChild).parent = this; | |
80 } | |
81 return newChild; | |
82 } | |
83 | |
84 /** | |
85 * Returns properties of this node interesting for debugging and can be overwritten by subclasses to add their own | |
86 * custom properties. | |
87 * | |
88 * @return the properties as a key/value hash map | |
89 */ | |
90 public Map<String, Object> getDebugProperties() { | |
91 Map<String, Object> properties = new HashMap<>(); | |
92 return properties; | |
93 } | |
94 | |
95 /** | |
96 * The current parent node of this node. | |
97 * | |
98 * @return the parent node | |
99 */ | |
100 public final Node getParent() { | |
101 return parent; | |
102 } | |
103 | |
104 /** | |
105 * Replaces one child of this node with another node. | |
106 * | |
107 * @param oldChild the old child | |
108 * @param newChild the new child that should replace the old child | |
109 * @return the new child | |
110 */ | |
111 public final <T extends Node> T replaceChild(T oldChild, T newChild) { | |
112 NodeUtil.replaceChild(this, oldChild, newChild); | |
113 adoptChild(newChild); | |
114 return newChild; | |
115 } | |
116 | |
117 /** | |
118 * Replaces this node with another node. | |
119 * | |
120 * @param newNode the new node that is the replacement | |
121 * @param reason a description of the reason for the replacement | |
122 * @return the new node | |
123 */ | |
124 @SuppressWarnings({"unchecked"}) | |
125 public <T extends Node> T replace(T newNode, String reason) { | |
126 assert this.getParent() != null; | |
127 return (T) this.getParent().replaceChild(this, newNode); | |
128 } | |
129 | |
130 /** | |
131 * Replaces this node with another node. | |
132 * | |
133 * @param newNode the new node that is the replacement | |
134 * @return the new node | |
135 */ | |
136 public <T extends Node> T replace(T newNode) { | |
137 return replace(newNode, ""); | |
138 } | |
139 | |
140 /** | |
141 * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all child nodes. | |
142 * | |
143 * @param nodeVisitor the visitor | |
144 */ | |
145 public final void accept(NodeVisitor nodeVisitor) { | |
146 if (nodeVisitor.visit(this)) { | |
147 for (Node child : this.getChildren()) { | |
148 if (child != null) { | |
149 child.accept(nodeVisitor); | |
150 } | |
151 } | |
152 } | |
153 } | |
154 | |
155 /** | |
156 * Iterator over the children of this node. | |
157 * | |
158 * @return the iterator | |
159 */ | |
160 public final Iterable<Node> getChildren() { | |
161 final Node node = this; | |
162 return new Iterable<Node>() { | |
163 | |
164 public Iterator<Node> iterator() { | |
165 return new NodeUtil.NodeIterator(node); | |
166 } | |
167 }; | |
168 } | |
169 | |
170 /** | |
171 * Creates a shallow copy of this node. | |
172 * | |
173 * @return the new copy | |
174 */ | |
175 public Node copy() { | |
176 try { | |
177 return (Node) super.clone(); | |
178 } catch (CloneNotSupportedException e) { | |
179 return null; | |
180 } | |
181 } | |
182 | |
183 /** | |
184 * This method must never be called. It enforces that {@link Object#clone} is not directly called by subclasses. | |
185 * Use the {@link #copy()} method instead. | |
186 */ | |
187 @Override | |
188 @Deprecated | |
189 protected final Object clone() throws CloneNotSupportedException { | |
190 throw new IllegalStateException("This method should never be called, use the copy method instead!"); | |
191 } | |
192 | |
193 /** | |
194 * Converts this node to a textual representation useful for debugging. | |
195 */ | |
196 @Override | |
197 public String toString() { | |
198 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); | |
199 Map<String, Object> properties = getDebugProperties(); | |
200 boolean hasProperties = false; | |
201 for (Map.Entry<String, Object> entry : properties.entrySet()) { | |
202 sb.append(hasProperties ? "," : "<"); | |
203 hasProperties = true; | |
204 sb.append(entry.getKey()).append("=").append(entry.getValue()); | |
205 } | |
206 if (hasProperties) { | |
207 sb.append(">"); | |
208 } | |
209 sb.append("@").append(Integer.toHexString(hashCode())); | |
210 return sb.toString(); | |
211 } | |
212 } |