Sha256: 2e06f9b9a6488d54a26bc1650b1952853027699916fc5644d9a3d9210e209c11
Contents?: true
Size: 1.75 KB
Versions: 69
Compression:
Stored size: 1.75 KB
Contents
defmodule Graph do defstruct attrs: [], nodes: [], edges: [] end defmodule Dot do # Normally matching on keywords is a bad idea as keyword lists can have # several orders (i.e. `[a: 1, b: 2]` and `[b: 2, a: 1]`). But in this case # only one keyword is allowed, so it's safe. defmacro graph(do: ast) do g = do_graph(ast) Macro.escape(%Graph{ attrs: Enum.sort(g.attrs), nodes: Enum.sort(g.nodes), edges: Enum.sort(g.edges) }) end defp do_graph(nil) do %Graph{} end defp do_graph({:__block__, _, stmts}) do Enum.reduce(stmts, %Graph{}, &do_stmt/2) end defp do_graph(stmt) do do_stmt(stmt, %Graph{}) end defp do_stmt(stmt = {:graph, _, [kws]}, g) when is_list(kws) do if Keyword.keyword?(kws) do %{g | attrs: kws ++ g.attrs} else raise_invalid_stmt(stmt) end end defp do_stmt({atom, _, nil}, g) when is_atom(atom) and atom != :-- do %{g | nodes: [{atom, []} | g.nodes]} end defp do_stmt(stmt = {atom, _, [kws]}, g) when is_atom(atom) and atom != :-- and is_list(kws) do if Keyword.keyword?(kws) do %{g | nodes: [{atom, kws} | g.nodes]} else raise_invalid_stmt(stmt) end end defp do_stmt({:--, _, [{a, _, nil}, {b, _, nil}]}, g) when is_atom(a) and is_atom(b) do %{g | edges: [{a, b, []} | g.edges]} end defp do_stmt(stmt = {:--, _, [{a, _, nil}, {b, _, [kws]}]}, g) when is_atom(a) and is_atom(b) and is_list(kws) do if Keyword.keyword?(kws) do %{g | edges: [{a, b, kws} | g.edges]} else raise_invalid_stmt(stmt) end end defp do_stmt(stmt, _) do raise_invalid_stmt(stmt) end defp raise_invalid_stmt(stmt) do raise ArgumentError, message: "Invalid statement: #{inspect(stmt)}" end end
Version data entries
69 entries across 69 versions & 1 rubygems