1 /*
2  * Copyright (c) 2011, 2018, 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 
24 
25 package org.graalvm.graphio;
26 
27 import java.util.Collection;
28 import java.util.Map;
29 
30 /**
31  * Interface that defines structure of a compiler graph. The structure of a graph is composed from
32  * nodes with properties, the classes of individual nodes, and ports associated with each node that
33  * may contain edges to other nodes. The structure of a graph is assumed to be immutable for the
34  * time of {@link GraphOutput operations} on it.
35  *
36  * @param <G> the type of the (root node of a) graph
37  * @param <N> the type of nodes
38  * @param <C> the type of node classes
39  * @param <P> the type of node ports
40  */
41 public interface GraphStructure<G, N, C, P> {
42     /**
43      * Casts {@code obj} to graph, if possible. If the given object <code>obj</code> can be seen as
44      * a graph or sub-graph of a graph, then return the properly typed instance. Otherwise return
45      * <code>null</code>
46      *
47      * @param currentGraph the currently processed graph
48      * @param obj an object to check and view as a graph
49      * @return appropriate graph object or <code>null</code> if the object doesn't represent a graph
50      */
graph(G currentGraph, Object obj)51     G graph(G currentGraph, Object obj);
52 
53     /**
54      * Nodes of a graph. Each graph is composed from a fixed set of nodes. This method returns an
55      * iterable which provides access to all of them - the number of nodes provided by the iterable
56      * must match the number returned by {@link #nodesCount(java.lang.Object)} method.
57      *
58      * @see #nodesCount(java.lang.Object)
59      * @param graph the graph to query for nodes
60      * @return iterable with all the graph's nodes
61      */
nodes(G graph)62     Iterable<? extends N> nodes(G graph);
63 
64     /**
65      * Number of nodes in a graph. The number must match the content returned by
66      * {@link #nodes(java.lang.Object)} method.
67      *
68      * @param graph the graph to query
69      * @return the number of nodes that will be returned by {@link #nodes(java.lang.Object)}
70      */
nodesCount(G graph)71     int nodesCount(G graph);
72 
73     /**
74      * Id of {@code node}. Each node in the graph is uniquely identified by an integer value. If two
75      * nodes have the same id, then they shall be <code>==</code> to each other.
76      *
77      * @param node the node to query for an id
78      * @return the id of the node
79      */
nodeId(N node)80     int nodeId(N node);
81 
82     /**
83      * Checks if there is a predecessor for a node.
84      *
85      * @param node the node to check
86      * @return <code>true</code> if it has a predecessor, <code>false</code> otherwise
87      */
nodeHasPredecessor(N node)88     boolean nodeHasPredecessor(N node);
89 
90     /**
91      * Collects node properties. Each node can be associated with additional properties identified
92      * by their name. This method shall copy them into the provided map.
93      *
94      * @param graph the current graph
95      * @param node the node to collect properties for
96      * @param properties the map to put the properties to
97      */
nodeProperties(G graph, N node, Map<String, ? super Object> properties)98     void nodeProperties(G graph, N node, Map<String, ? super Object> properties);
99 
100     /**
101      * Finds a node for {@code obj}, if possible. If the given object <code>obj</code> can be seen
102      * as an instance of node return the properly typed instance of the node class. Otherwise return
103      * <code>null</code>.
104      *
105      * @param obj an object to find node for
106      * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
107      */
node(Object obj)108     N node(Object obj);
109 
110     /**
111      * Finds a node class for {@code obj}, if possible. If the given object <code>obj</code> can be
112      * seen as an instance of node class return the properly typed instance of the node class.
113      * Otherwise return <code>null</code>.
114      *
115      * @param obj an object to find node class for
116      * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
117      *         class
118      */
nodeClass(Object obj)119     C nodeClass(Object obj);
120 
121     /**
122      * Finds a node class for {@code node}.
123      *
124      * @param node an instance of node in this graph
125      * @return the node's node class, never <code>null</code>
126      */
classForNode(N node)127     C classForNode(N node);
128 
129     /**
130      * The template used to build the name of nodes of this class. The template may use references
131      * to inputs (&#123;i#inputName&#125;) and its properties (&#123;p#propertyName&#125;).
132      *
133      * @param nodeClass the node class to find name template for
134      * @return the string representing the template
135      */
nameTemplate(C nodeClass)136     String nameTemplate(C nodeClass);
137 
138     /**
139      * Java class for a node class.
140      *
141      * @param nodeClass the node class
142      * @return the {@link Class} or other type representation of the node class
143      */
nodeClassType(C nodeClass)144     Object nodeClassType(C nodeClass);
145 
146     /**
147      * Input ports of a node class. Each node class has a fixed set of ports where individual edges
148      * can attach to.
149      *
150      * @param nodeClass the node class
151      * @return input ports for the node class
152      */
portInputs(C nodeClass)153     P portInputs(C nodeClass);
154 
155     /**
156      * Output ports of a node class. Each node class has a fixed set of ports from where individual
157      * edges can point to other nodes.
158      *
159      * @param nodeClass the node class
160      * @return output ports for the node class
161      */
portOutputs(C nodeClass)162     P portOutputs(C nodeClass);
163 
164     /**
165      * The number of edges in a port. The protocol will then call methods
166      * {@link #edgeDirect(java.lang.Object, int)}, {@link #edgeName(java.lang.Object, int)},
167      * {@link #edgeType(java.lang.Object, int)} and
168      * {@link #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int)} for indexes
169      * from <code>0</code> to <code>portSize - 1</code>
170      *
171      * @param port the port
172      * @return number of edges in this port
173      */
portSize(P port)174     int portSize(P port);
175 
176     /**
177      * Checks whether an edge is direct. Direct edge shall have exactly one
178      * {@linkplain #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int) node} - it
179      * is an error to return more than one for such an edge from the
180      * {@linkplain #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int) method}.
181      *
182      * @param port the port
183      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
184      *            <code>1</code>
185      * @return <code>true</code> if only one node can be returned from
186      *         {@link #edgeNodes(java.lang.Object, java.lang.Object, java.lang.Object, int)} method
187      */
edgeDirect(P port, int index)188     boolean edgeDirect(P port, int index);
189 
190     /**
191      * The name of an edge.
192      *
193      * @param port the port
194      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
195      *            <code>1</code>
196      * @return the name of the edge
197      */
edgeName(P port, int index)198     String edgeName(P port, int index);
199 
200     /**
201      * Type of an edge. The type must be a graph
202      * <q>enum</q> - e.g. either real instance of {@link Enum} subclass, or something that the
203      * {@link GraphOutput.Builder} can recognize as
204      * <q>enum</q>.
205      *
206      * @param port
207      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
208      *            <code>1</code>
209      * @return any {@link Enum} representing type of the edge
210      */
edgeType(P port, int index)211     Object edgeType(P port, int index);
212 
213     /**
214      * Nodes where the edges for a port lead to/from. This method is called for both
215      * {@link #edgeDirect(java.lang.Object, int) direct/non-direct edges}. In case of a direct edge
216      * the returned collection must have exactly one element.
217      *
218      * @param graph the graph
219      * @param node the node in the graph
220      * @param port port of the node class
221      * @param index index from <code>0</code> to {@link #portSize(java.lang.Object)} minus
222      *            <code>1</code>
223      * @return <code>null</code> if there are no edges associated with given port or collection of
224      *         nodes where to/from the edges lead to
225      */
edgeNodes(G graph, N node, P port, int index)226     Collection<? extends N> edgeNodes(G graph, N node, P port, int index);
227 }
228