flow_graph.erl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. -module(flow_graph).
  2. % Vertex construction
  3. -export([hole/0, value/1, void/0, split/0, merge/0, switch/2, select/2]).
  4. % Edge construction
  5. -export([flow/2, func/3, index/3, range/4, tagged/3, dynamic/2, dynamic/3]).
  6. % Graph construction
  7. -export([singleton/1, from_list/3]).
  8. % Graph manipulation
  9. -export([append/2, out_edges/2]).
  10. % Checks for validity
  11. -export([valid_edge/1, valid_edge_list/1, valid_graph/1]).
  12. % Use the orddict module for clarity, and the dict module for speed.
  13. -define(DICT, orddict).
  14. % flow_graph ::= {in : vertex,
  15. % out : vertex,
  16. % graph : dict(vertex, [edge])}
  17. -record(flow_graph, {in, out, graph}).
  18. % vertex ::= {ref, node}
  19. -record(vertex, {ref, node}).
  20. % node ::= hole | value | void | split | merge | switch | select | delayed
  21. % value ::= term
  22. % switch ::= {fun(A, State) -> {Tag, State}, State}
  23. % select ::= {fun(A, State) -> {select, State} | {block, State}, State}
  24. -record(value, {value}).
  25. -record(switch, {switch, state}).
  26. -record(select, {select, state}).
  27. % edge ::= {from : vertex, to : vertex, through : link
  28. -record(edge, {from, to, through}).
  29. % link ::= flow | func | range | tagged | dynamic
  30. % func ::= fun(A) -> B
  31. % range ::= {int, int}
  32. % tagged ::= Tag
  33. % dyanmic ::= fun(A) -> flow_graph
  34. -record(func, {func}).
  35. -record(range, {from, to}).
  36. -record(tagged, {tag}).
  37. -record(dynamic, {code}).
  38. %% Vertex construction
  39. make_vertex(N) ->
  40. #vertex{ref=make_ref(), node=N}.
  41. hole() ->
  42. make_vertex(hole).
  43. value(X) ->
  44. make_vertex(#value{value=X}).
  45. void() ->
  46. make_vertex(void).
  47. split() ->
  48. make_vertex(split).
  49. merge() ->
  50. make_vertex(merge).
  51. switch(Switch, Init) when is_function(Switch) ->
  52. make_vertex(#switch{switch=Switch, state=Init}).
  53. select(Select, Init) when is_function(Select) ->
  54. make_vertex(#select{select=Select, state=Init}).
  55. delayed() ->
  56. make_vertex(delayed).
  57. %% Edge construction
  58. make_edge(From, To, Through) ->
  59. #edge{from=From, to=To, through=Through}.
  60. flow(From, To) ->
  61. make_edge(From, To, flow).
  62. func(From, To, Func) ->
  63. make_edge(From, To, #func{func=Func}).
  64. index(From, To, N) when is_number(N) ->
  65. range(From, To, N, N).
  66. range(From, To, Low, High) when is_number(Low), is_number(High), Low =< High->
  67. make_edge(From, To, #range{from=Low, to=High}).
  68. tagged(From, To, Tag) ->
  69. make_edge(From, To, #tagged{tag=Tag}).
  70. dynamic(From, To = #vertex{node=delayed}, Code) ->
  71. make_edge(From, To, #dynamic{code=Code}).
  72. dynamic(From, Code) ->
  73. make_edge(From, delayed(), #dynamic{code=Code}).
  74. %% Graph constructon
  75. singleton(V = #vertex{}) ->
  76. #flow_graph{in=V, out=V, graph=orddict:store(V, [], ?DICT:new())}.
  77. from_list(In = #vertex{}, Out = #vertex{}, Edges) ->
  78. FG = lists:foldl(fun(E, G) -> add_edge(G, E) end,
  79. #flow_graph{in=In, out=Out, graph=?DICT:new()},
  80. Edges),
  81. G2 = ?DICT:update(Out, fun(X)->X end, [], FG#flow_graph.graph),
  82. FG#flow_graph{graph=G2}.
  83. %% Graph manipulation
  84. append(FG1 = #flow_graph{in=In1, out=Out1},
  85. FG2 = #flow_graph{in=In2, out=Out2}) ->
  86. G = ?DICT:merge(fun(_, E1, E2) -> lists:append(E1,E2) end,
  87. FG1#flow_graph.graph,
  88. FG2#flow_graph.graph),
  89. add_edge(#flow_graph{in=In1, out=Out2, graph=G},
  90. flow(Out1, In2)).
  91. out_edges(#flow_graph{graph=G}, #vertex{ref=R}) ->
  92. ?DICT:find(R, G).
  93. add_edge(FG = #flow_graph{graph=G}, E = #edge{from=From}) ->
  94. Add = fun(Edges) -> [E|Edges] end,
  95. FG#flow_graph{graph=?DICT:update(From, Add, [E], G)}.
  96. % Checks for validity
  97. valid_edge(#edge{from=From, to=To, through=Through}) ->
  98. IsNeutral = fun(flow) -> true;
  99. (#func{}) -> true;
  100. (#dynamic{}) -> true;
  101. (_) -> false
  102. end,
  103. Left = case {From, Through, To} of
  104. {delayed, _, _} -> false;
  105. {hole, _, _} -> IsNeutral(Through);
  106. {#value{}, _, _} -> IsNeutral(Through);
  107. {void, flow, #value{}} -> true;
  108. {void, flow, void} -> true;
  109. {void, #dynamic{}, delayed} -> true;
  110. {void, _, _} -> false;
  111. {split, #range{}, _} -> true;
  112. {split, _, _} -> false;
  113. {merge, _, _} -> IsNeutral(Through);
  114. {#switch{}, #tagged{}, _} -> true;
  115. {#switch{}, _, _} -> false;
  116. {#select{}, _, _} -> IsNeutral(Through);
  117. _ -> false
  118. end,
  119. Right = case {From, Through, To} of
  120. {_, dynamic, delayed} -> true;
  121. {_, dynamic, _} -> false;
  122. {_, _, hole} -> true;
  123. {void, flow, #value{}} -> true;
  124. {_, _, #value{}} -> false;
  125. {void, flow, void} -> true;
  126. {_, _, void} -> false;
  127. {_, _, split} -> true;
  128. {_, #range{}, merge} -> true;
  129. {_, _, merge} -> false;
  130. {_, _, #switch{}} -> true;
  131. {_, _, #select{}} -> true
  132. end,
  133. Left and Right.
  134. valid_edge_list(Edges) ->
  135. lists:all(fun valid_edge/1, Edges).
  136. valid_graph(#flow_graph{graph=G}) ->
  137. lists:all(fun({_, Es}) -> valid_edge_list(Es) end,
  138. ?DICT:to_list(G)).