1 (* Copyright (C) 2009,2017 Matthew Fluet.
2 * Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
9 signature DIRECTED_GRAPH =
16 val equals: 'a t * 'a t -> bool
17 val hasEdge: {from: 'a t, to: 'a t} -> bool
18 val layout: 'a t -> Layout.t
19 val plist: 'a t -> PropertyList.t
20 val successors: 'a t -> 'a edge list
26 val equals: 'a t * 'a t -> bool
27 val layout: 'a t -> Layout.t
28 val plist: 'a t -> PropertyList.t
29 val to: 'a t -> 'a Node.t
31 sharing type Node.edge = Edge.t
33 (* depth first search *)
36 type ('a, 'b, 'c, 'd, 'e) t =
40 * ('a Node.t * 'c -> ('d
41 * ('a Edge.t * 'd -> 'd)
42 * ('a Edge.t * 'd -> 'c * ('e -> 'd))
45 type ('a, 'b) u = ('a, 'b, 'b, 'b, 'b) t
47 val discoverFinishTimes:
48 unit -> (('a, int) u * {discover: 'a Node.t -> int,
49 finish: 'a Node.t -> int,
50 destroy: unit -> unit})
51 val finishNode: ('a Node.t -> unit) -> ('a, unit) u
52 val startNode: ('a Node.t -> unit) -> ('a, unit) u
55 (* the main graph type *)
59 val addEdge: 'a t * {from: 'a Node.t, to: 'a Node.t} -> 'a Edge.t
60 val coerce: 'a t -> unit t * {edge: 'a Edge.t -> unit Edge.t,
61 node: 'a Node.t -> unit Node.t}
62 val dfs: 'a t * ('a, 'b, 'c, 'd, 'e) DfsParam.t -> 'b
63 val dfsForest: 'a t * {roots: 'a Node.t vector,
64 nodeValue: 'a Node.t -> 'b} -> 'b Tree.t vector
65 val dfsNodes: 'a t * 'a Node.t list * ('a, 'b, 'c, 'd, 'e) DfsParam.t -> 'b
66 val dfsTree: 'a t * {root: 'a Node.t,
67 nodeValue: 'a Node.t -> 'b} -> 'b Tree.t
70 layoutNode: 'a Node.t -> Layout.t,
71 display: Layout.t -> unit} -> unit
72 (* dominators (graph, {root})
73 * Returns the immediate dominator relation for the subgraph of graph
75 * idom n = Root if n = root
76 * idom n = Idom n' where n' is the immediate dominator of n
77 * idom n = Unreachable if n is not reachable from root
83 val dominators: 'a t * {root: 'a Node.t} -> {idom: 'a Node.t -> 'a idomRes}
84 val dominatorTree: 'a t * {root: 'a Node.t,
85 nodeValue: 'a Node.t -> 'b} -> 'b Tree.t
86 val foreachDescendent: 'a t * 'a Node.t * ('a Node.t -> unit) -> unit
87 val foldNodes: 'a t * 'b * ('a Node.t * 'b -> 'b) -> 'b
88 val foreachEdge: 'a t * ('a Node.t * 'a Edge.t -> unit) -> unit
89 val foreachNode: 'a t * ('a Node.t -> unit) -> unit
90 (* ignoreNodes (g, f) builds a graph g' that looks like g, except that g'
91 * does not contain nodes n such that f n, and that for every path in g
92 * of the form n0 -> n1 -> ... -> nm, where n0 and nm are not ignored and
93 * n1, ..., n_m-1 are ignored, there is an edge in g'.
96 'a t * ('a Node.t -> bool)
97 -> 'a u t * {destroy: unit -> unit,
98 newNode: 'a Node.t -> 'a u Node.t}
100 'a t * ({nodeName: 'a Node.t -> string}
101 -> {edgeOptions: 'a Edge.t -> Dot.EdgeOption.t list,
102 nodeOptions: 'a Node.t -> Dot.NodeOption.t list,
103 options: Dot.GraphOption.t list,
106 structure LoopForest:
110 val dest: 'a t -> {loops: {headers: 'a Node.t vector,
112 notInLoop: 'a Node.t vector}
114 'a t * {nodeName: 'a Node.t -> string,
115 options: Dot.GraphOption.t list,
119 val loopForestSteensgaard: 'a t * {root: 'a Node.t} -> 'a LoopForest.t
120 val new: unit -> 'a t
121 val newNode: 'a t -> 'a Node.t
122 val nodes: 'a t -> 'a Node.t list
123 val numNodes: 'a t -> int
125 * Pre: v should be an equivalence relation on the nodes of g. That is,
126 * each node in g should appear exactly once in some vector in v.
127 * The result is a graph with one node per equivalence class, and an edge
128 * between classes iff there is an edge between nodes in the classes.
131 'a t * ('a Node.t vector vector)
132 -> 'a u t * {destroy: unit -> unit,
133 newNode: 'a Node.t -> 'a u Node.t}
134 (* Removes node and incident edges. *)
135 val removeNode: 'a t * 'a Node.t -> unit
136 val removeDuplicateEdges: 'a t -> unit
137 (* Strongly-connected components.
138 * Each component is given as a list of nodes.
139 * The components are returned topologically sorted.
141 val stronglyConnectedComponents: 'a t -> 'a Node.t list list
143 'a t * ('a Node.t -> bool)
144 -> 'a u t * {destroy: unit -> unit,
145 newNode: 'a Node.t -> 'a u Node.t}
146 (* topologicalSort g returns NONE if there is a cycle in g.
147 * Otherwise, returns then nodes in g in a list such that if there is a
148 * path in g from n to n', then n appears before n' in the list.
150 val topologicalSort: 'a t -> 'a Node.t list option
151 val transpose: 'a t -> 'a u t * {destroy: unit -> unit,
152 newNode: 'a Node.t -> 'a u Node.t}
156 functor TestDirectedGraph (S: DIRECTED_GRAPH): sig end =
161 (* Section 7.3 of Muchnick. *)
164 val {get = name, set = setName, ...} =
165 Property.getSetOnce (Node.plist,
166 Property.initRaise ("name", Node.layout))
167 val node = String.memoize (fn s =>
170 val _ = setName (n, s)
174 List.foreach ([("entry\nfoo", "B1"),
182 ("B6", "B4")], fn (from, to) =>
183 ignore (addEdge (g, {from = node from, to = node to})))
186 ("/tmp/z.dot", fn out =>
190 Layout.output (layoutDot
194 edgeOptions = fn _ => [],
195 nodeOptions = fn n => [NodeOption.label (name n)]}),
199 val {idom} = dominators (g, {root = node "entry\nfoo"})
201 val {get = oldNode, set = setOldNode, ...} =
202 Property.getSetOnce (Node.plist,
203 Property.initRaise ("oldNode", Node.layout))
204 val {get = newNode, ...} =
205 Property.get (Node.plist,
206 Property.initFun (fn n =>
209 val _ = setOldNode (n', n)
212 val _ = foreachNode (g, fn n =>
215 ignore (addEdge (g2, {from = newNode n',
220 ("/tmp/z2.dot", fn out =>
229 edgeOptions = fn _ => [],
230 nodeOptions = fn n => [NodeOption.label (name (oldNode n))]}),