Mercurial > hg > graal-compiler
view graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 7543:be0d995ef51e
factored out code common to SystemSubstitutions.identityHashCode() and ObjectSubstitutions.hashCode()
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 23 Jan 2013 22:37:22 +0100 |
parents | 5e3d1a68664e |
children | 4497235516df |
line wrap: on
line source
/* * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.truffle.api.nodes; import java.lang.annotation.*; import java.util.*; /** * Abstract base class for all Truffle nodes. */ public abstract class Node implements Cloneable { /** * Utility constant representing an empty node array. */ public static final Node[] EMPTY_ARRAY = new Node[0]; private Node parent; /** * Marks array fields that are children of this node. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Children { } /** * Marks fields that represent child nodes of this node. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Child { } /** * Method that updates the link to the parent in the array of specified new child nodes to this * node. * * @param newChildren the array of new children whose parent should be updated * @return the array of new children */ protected final <T extends Node> T[] adoptChildren(T[] newChildren) { if (newChildren != null) { for (T n : newChildren) { adoptChild(n); } } return newChildren; } /** * Method that updates the link to the parent in the specified new child node to this node. * * @param newChild the new child whose parent should be updated * @return the new child */ protected final <T extends Node> T adoptChild(T newChild) { if (newChild != null) { ((Node) newChild).parent = this; } return newChild; } /** * Returns properties of this node interesting for debugging and can be overwritten by * subclasses to add their own custom properties. * * @return the properties as a key/value hash map */ public Map<String, Object> getDebugProperties() { Map<String, Object> properties = new HashMap<>(); return properties; } /** * The current parent node of this node. * * @return the parent node */ public final Node getParent() { return parent; } /** * Replaces one child of this node with another node. * * @param oldChild the old child * @param newChild the new child that should replace the old child * @return the new child */ public final <T extends Node> T replaceChild(T oldChild, T newChild) { NodeUtil.replaceChild(this, oldChild, newChild); adoptChild(newChild); return newChild; } /** * Replaces this node with another node. * * @param newNode the new node that is the replacement * @param reason a description of the reason for the replacement * @return the new node */ @SuppressWarnings({"unchecked"}) public <T extends Node> T replace(T newNode, String reason) { assert this.getParent() != null; return (T) this.getParent().replaceChild(this, newNode); } /** * Replaces this node with another node. * * @param newNode the new node that is the replacement * @return the new node */ public <T extends Node> T replace(T newNode) { return replace(newNode, ""); } /** * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all * child nodes. * * @param nodeVisitor the visitor */ public final void accept(NodeVisitor nodeVisitor) { if (nodeVisitor.visit(this)) { for (Node child : this.getChildren()) { if (child != null) { child.accept(nodeVisitor); } } } } /** * Iterator over the children of this node. * * @return the iterator */ public final Iterable<Node> getChildren() { final Node node = this; return new Iterable<Node>() { public Iterator<Node> iterator() { return new NodeUtil.NodeIterator(node); } }; } /** * Creates a shallow copy of this node. * * @return the new copy */ public Node copy() { try { return (Node) super.clone(); } catch (CloneNotSupportedException e) { return null; } } /** * This method must never be called. It enforces that {@link Object#clone} is not directly * called by subclasses. Use the {@link #copy()} method instead. */ @Override @Deprecated protected final Object clone() throws CloneNotSupportedException { throw new IllegalStateException("This method should never be called, use the copy method instead!"); } /** * Converts this node to a textual representation useful for debugging. */ @Override public String toString() { StringBuilder sb = new StringBuilder(getClass().getSimpleName()); Map<String, Object> properties = getDebugProperties(); boolean hasProperties = false; for (Map.Entry<String, Object> entry : properties.entrySet()) { sb.append(hasProperties ? "," : "<"); hasProperties = true; sb.append(entry.getKey()).append("=").append(entry.getValue()); } if (hasProperties) { sb.append(">"); } sb.append("@").append(Integer.toHexString(hashCode())); return sb.toString(); } }