1 (* Copyright (C) 2009 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_SUB_GRAPH =
11 (* the main graph type *)
20 val equals: t * t -> bool
21 val hasEdge: graph * {from: t, to: t} -> bool
22 val layout: t -> Layout.t
23 val plist: t -> PropertyList.t
24 val successors: graph * t -> edge list
32 val equals: t * t -> bool
33 val from: graph * t -> node
34 val plist: t -> PropertyList.t
35 val to: graph * t -> node
37 sharing type Node.edge = Edge.t
38 sharing type Edge.node = Node.t
39 sharing type Node.graph = t
40 sharing type Edge.graph = t
42 (* depth first search *)
45 type t = {startNode: Node.t -> unit,
46 finishNode: Node.t -> unit,
47 handleTreeEdge: Edge.t -> unit,
48 handleNonTreeEdge: Edge.t -> unit,
49 startTree: Node.t -> unit,
50 finishTree: Node.t -> unit,
51 finishDfs: unit -> unit}
52 val finishNode: (Node.t -> unit) -> t
53 val ignore: 'a -> unit
54 val combine: t * t -> t
57 (* create a sub-graph from a graph *)
58 val subGraph: t * {nodeP: Node.t -> bool, edgeP: Edge.t -> bool} -> t
61 val addEdge: t * {from: Node.t, to: Node.t} -> Edge.t
62 val dfs: t * DfsParam.t -> unit
63 val dfsNodes: t * Node.t list * DfsParam.t -> unit
64 val discoverFinishTimes: t -> {discover: Node.t -> int,
65 finish: Node.t -> int,
66 destroy: unit -> unit,
70 layoutNode: Node.t -> Layout.t,
71 display: Layout.t -> unit} -> unit
72 (* dominators {graph, root}
73 * Pre: All nodes in graph must be reachable from root.
74 * This condition is checked.
76 * idom n = the immediate dominator n.
79 val dominators: t * {root: Node.t} -> {idom: Node.t -> Node.t}
80 val dominatorTree: t * {root: Node.t, nodeValue: Node.t -> 'a} -> 'a Tree.t
81 val foreachDescendent: t * Node.t * (Node.t -> unit) -> unit
82 val foreachEdge: t * (Node.t * Edge.t -> unit) -> unit
83 val foreachNode: t * (Node.t -> unit) -> unit
85 (* val input: In.t * (In.t -> 'a)* (In.t -> 'b) -> t * 'a * (Edge.t -> 'b) *)
86 (* val isCyclic: t -> bool*)
89 options: Dot.GraphOption.t list,
90 edgeOptions: Edge.t -> Dot.EdgeOption.t list,
91 nodeOptions: Node.t -> Dot.NodeOption.t list} -> Layout.t
93 {headers: (* graph *) Node.t list -> (* graph *) Node.t list,
95 root: (* graph *) Node.t}
97 graphToForest: (* graph *) Node.t -> (* forest *) Node.t,
98 headers: (* graph *) Node.t list -> (* graph *) Node.t list,
99 isHeader: (* graph *) Node.t -> bool,
100 loopNodes: (* forest *) Node.t -> (* graph *) Node.t list,
101 parent: (* forest *) Node.t -> (* forest *) Node.t option}
102 val loopForestSteensgaard:
104 root: (* graph *) Node.t}
106 graphToForest: (* graph *) Node.t -> (* forest *) Node.t,
107 headers: (* graph *) Node.t list -> (* graph *) Node.t list,
108 isHeader: (* graph *) Node.t -> bool,
109 loopNodes: (* forest *) Node.t -> (* graph *) Node.t list,
110 parent: (* forest *) Node.t -> (* forest *) Node.t option}
112 val newNode: t -> Node.t
113 val nodes: t -> Node.t list
114 (* val random: {numNodes: int, numEdges: int} -> t*)
115 (* val removeBackEdges: t -> unit *)
116 (* removeEdge fails if edge isn't there. *)
117 (* val removeEdge: t * Edge.t -> unit *)
118 (* Strongly-connected components.
119 * Each component is given as a list of nodes.
120 * The components are returned topologically sorted.
122 val stronglyConnectedComponents: t -> Node.t list list
123 exception TopologicalSort
124 val topologicalSort: t -> Node.t list
125 (* val transpose: t -> t *)
129 functor TestDirectedSubGraph (S: DIRECTED_SUB_GRAPH): sig end =
134 (* Section 7.3 of Muchnick. *)
137 val {get = name, set = setName, ...} =
138 Property.getSetOnce (Node.plist,
139 Property.initRaise ("name", Node.layout))
140 val node = String.memoize (fn s =>
143 val _ = setName (n, s)
147 List.foreach ([("entry\nfoo", "B1"),
155 ("B6", "B4")], fn (from, to) =>
156 ignore (addEdge (g, {from = node from, to = node to})))
159 ("/tmp/z.dot", fn out =>
163 Layout.output (layoutDot
167 edgeOptions = fn _ => [],
168 nodeOptions = fn n => [NodeOption.label (name n)]}),
172 val {idom} = dominators (g, {root = node "entry\nfoo"})
174 val {get = oldNode, set = setOldNode, ...} =
175 Property.getSetOnce (Node.plist,
176 Property.initRaise ("oldNode", Node.layout))
177 val {get = newNode, ...} =
178 Property.get (Node.plist,
179 Property.initFun (fn n =>
182 val _ = setOldNode (n', n)
185 val _ = foreachNode (g, fn n =>
186 ignore (addEdge (g2, {from = newNode (idom n),
190 ("/tmp/z2.dot", fn out =>
198 edgeOptions = fn _ => [],
199 nodeOptions = fn n => [NodeOption.label (name (oldNode n))]}),