Packages

fun_pipelinex is a package which filter function's args and return value by your custom Filters.

Current section

Files

Jump to
fun_pipelinex lib parser.ex
Raw

lib/parser.ex

defmodule FunPipelinex.Parser do
@moduledoc false
alias FunPipelinex.{Error, Helper}
@allowed_fun_types [:def]
@not_support_types [:@, :defmodule, :use, :require, :import, :alias]
###
def parse_fun({:__block__, _, [_ | _] = block}), do: parse_fun(block, [])
def parse_fun(block), do: parse_fun([block], [])
def parse_fun([], funs), do: Enum.reverse(funs)
def parse_fun([expr | rest], funs) do
fun = do_parse_fun(expr, %{})
parse_fun(rest, [fun | funs])
end
defp do_parse_fun({type, _, fun}, parts) when type in @allowed_fun_types do
do_parse_fun(fun, parts)
end
defp do_parse_fun([{:when, _, fa_guard}, [{:do, block}]], parts) do
fa_guard
|> do_parse_fun(parts)
|> Map.put(:block, block)
end
defp do_parse_fun([fa, [{:do, block}]], parts) do
fa
|> do_parse_fun(parts)
|> Map.put(:block, block)
|> Map.put(:guard, true)
end
defp do_parse_fun([fa, guard], parts) do
fa
|> do_parse_fun(parts)
|> Map.put(:guard, guard)
end
defp do_parse_fun({f, _, [{_, _, _} | _] = a}, parts) when f not in @not_support_types do
parts
|> Map.put(:f, f)
|> Map.put(:a, a)
end
defp do_parse_fun({f, _, _}, parts) when f not in @not_support_types do
parts
|> Map.put(:f, f)
|> Map.put(:a, [])
end
defp do_parse_fun({type, _, [_ | _]}, _parts), do: raise(Error, "not support #{type}")
defp do_parse_fun(_other_expr, _parts), do: raise(Error, "unknown function")
###
def parse_filters({:__block__, _, filter_expr}), do: do_parse_filters(filter_expr, [])
def parse_filters(filter_expr), do: do_parse_filters([filter_expr], [])
def do_parse_filters([], filters), do: Enum.dedup(filters)
def do_parse_filters([{:filter, _, [{:__aliases__, _, term}]} | rest], filters),
do: do_parse_filters(rest, [Helper.make_m_name(term) | filters])
def do_parse_filters([{:filter, _, [f_name]} | rest], filters) when is_atom(f_name),
do: do_parse_filters(rest, [f_name | filters])
end