<commit_before>defrecord Graph, attrs: [], nodes: [], edges: []

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.update(attrs: (Code.eval_quoted(kws) |> elem(0)) ++ g.attrs)
    else
      raise_invalid_stmt(stmt)
    end
  end
  defp do_stmt({atom, _, nil}, g) when is_atom(atom) and atom != :-- do
    g.update(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.update(nodes: [{atom, Code.eval_quoted(kws) |> elem(0)} | 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.update(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.update(edges: [{a, b, Code.eval_quoted(kws) |> elem(0)} | g.edges])<commit_msg>Avoid Code.eval_quoted in elixir dot-dsl<commit_after>defrecord Graph, attrs: [], nodes: [], edges: []

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.new(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.update(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.update(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.update(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.update(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.update(edges: [{a, b, kws} | g.edges])
{'fraction_non_alphanumeric': 0.17348808796579107, 'fraction_numerical': 0.003970678069639585, 'mean_word_length': 2.8941736028537455, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4026383', 'n_tokens_mistral': 1332, 'n_tokens_neox': 1311, 'n_words': 348}