001/*
002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.graph;
024
025import com.oracle.graal.nodeinfo.*;
026
027/**
028 * Describes an edge slot for a {@link NodeClass}.
029 */
030public final class Position {
031
032    /**
033     * The edges in which this position lies.
034     */
035    private final Edges edges;
036
037    /**
038     * Index of the {@link Node} or {@link NodeList} field denoted by this position.
039     */
040    private final int index;
041
042    /**
043     * Index within a {@link NodeList} if {@link #index} denotes a {@link NodeList} field otherwise
044     * {@link Node#NOT_ITERABLE}.
045     */
046    private final int subIndex;
047
048    public Position(Edges edges, int index, int subIndex) {
049        this.edges = edges;
050        this.index = index;
051        this.subIndex = subIndex;
052    }
053
054    public Node get(Node node) {
055        if (index < edges.getDirectCount()) {
056            return Edges.getNode(node, edges.getOffsets(), index);
057        } else {
058            return Edges.getNodeList(node, edges.getOffsets(), index).get(subIndex);
059        }
060    }
061
062    public InputType getInputType() {
063        return ((InputEdges) edges).getInputType(index);
064    }
065
066    public String getName() {
067        return edges.getName(index);
068    }
069
070    public boolean isInputOptional() {
071        return ((InputEdges) edges).isOptional(index);
072    }
073
074    public void set(Node node, Node value) {
075        if (index < edges.getDirectCount()) {
076            edges.setNode(node, index, value);
077        } else {
078            Edges.getNodeList(node, edges.getOffsets(), index).set(subIndex, value);
079        }
080    }
081
082    public void initialize(Node node, Node value) {
083        if (index < edges.getDirectCount()) {
084            Edges.initializeNode(node, edges.getOffsets(), index, value);
085        } else {
086            Edges.getNodeList(node, edges.getOffsets(), index).initialize(subIndex, value);
087        }
088    }
089
090    @Override
091    public String toString() {
092        String res = edges.getType(index).getSimpleName() + ":" + edges.getName(index);
093        if (subIndex != Node.NOT_ITERABLE) {
094            res += "[" + subIndex + "]";
095        }
096        return res;
097    }
098
099    @Override
100    public int hashCode() {
101        final int prime = 31;
102        int result = 1;
103        result = prime * result + index;
104        result = prime * result + edges.hashCode();
105        result = prime * result + subIndex;
106        return result;
107    }
108
109    @Override
110    public boolean equals(Object obj) {
111        if (this == obj) {
112            return true;
113        }
114        if (obj == null) {
115            return false;
116        }
117        if (getClass() != obj.getClass()) {
118            return false;
119        }
120        Position other = (Position) obj;
121        if (index != other.index) {
122            return false;
123        }
124        if (edges != other.edges) {
125            return false;
126        }
127        if (subIndex != other.subIndex) {
128            return false;
129        }
130        return true;
131    }
132
133    /**
134     * Gets the index within a {@link NodeList} if {@link #getIndex()} denotes a {@link NodeList}
135     * field otherwise {@link Node#NOT_ITERABLE}.
136     */
137    public int getSubIndex() {
138        return subIndex;
139    }
140
141    /**
142     * Gets the index of the {@link Node} or {@link NodeList} field denoted by this position.
143     */
144    public int getIndex() {
145        return index;
146    }
147}