Current section
Files
Jump to
Current section
Files
lib/macros.ex
defmodule Pex.Macros do
@moduledoc false
alias Pex.Result
@value {:__VALUE__, [], __MODULE__}
defmacrop _(), do: quote([do: {:&, _, [1]}])
# Pipe into map
defmacro left |> {:%{}, meta, args} do
args = Enum.map(args, fn
{_(), _()} -> {left, left};
{_(), value} -> {left, value};
{key, _()} -> {key, left};
x -> x
end)
quote do
unquote({:ok, {:%{}, meta, args}})
end
end
# Pipe into list
defmacro left |> [{:|, _, [_(), tail]}], do: {:ok, [left | tail]}
defmacro left |> [{:|, _, [head, _()]}], do:
quote([do: {:ok, [unquote(head) | unquote(left)]}])
defmacro left |> right when is_list(right), do:
{:ok, Enum.map(right, fn _() -> left; x -> x end)}
# Pipe into function defintion
defmacro left |> ({:fn, meta, _} = fun), do:
result(:ok, left, {{:., meta, [fun]}, meta, []})
# Pipe into inspect with label
defmacro left |> {{:., meta_start, [aliases, :inspect]}, meta_end, args} do
label = if(length(args) == 1, do: [label: Enum.at(args, 0)], else: [])
quote do
unquote({{:., meta_start, [aliases, :inspect]}, meta_end, [left, label]})
end
end
# Default pipe definition
defmacro left |> right, do: result(:ok, left, right)
# Pipe errors into function defintion
defmacro left <~ ({:fn, meta, _} = fun), do:
result(:error, left, {{:., meta, [fun]}, meta, []})
# Pipe errors to function
defmacro left <~ right, do: result(:error, left, right)
defp place_arg([]), do: [@value]
defp place_arg(args), do: place_arg(args, false) || [@value | args]
defp place_arg([], true), do: []
defp place_arg([], false), do: false
defp place_arg([_() | tail], _), do: [@value | place_arg(tail, true)]
defp place_arg([head | tail], match), do: (tail = place_arg(tail, match)) && [head | tail]
defp result(side, left, {call, meta, args}) do
quote do
apply(Result, unquote(side), [
unquote(left),
fn unquote(@value) -> unquote({call, meta, place_arg(args)}) end
])
end
end
end