Current section
Files
Jump to
Current section
Files
lib/amnesia/hooks.ex
defmodule Amnesia.Hooks do
defmacro __using__(hooks) do
[ quote(do: import Amnesia.Hooks),
quote(do: @hooks unquote(hooks)) |
Enum.map(hooks, fn { name, arity } ->
args = Enum.map(1..arity, fn i ->
if i == arity do
Macro.var(:"arg#{i}", nil)
else
Macro.var(:"_arg#{i}", nil)
end
end)
last_arg = Macro.var(:"arg#{arity}", nil)
quote do
def unquote("hook_#{name}" |> String.to_atom)(unquote_splicing(args)) do
unquote(last_arg)
end
defoverridable [{ unquote("hook_#{name}" |> String.to_atom), unquote(arity) }]
end
end) ]
end
defmacro defhook({ :when, _, [{ name, _, args }, guard] }, do: body) do
quote do
unless Enum.find @hooks, fn { name, arity } ->
name == unquote(name) and arity == unquote(length(args))
end do
raise ArgumentError, message: "unknown #{unquote(name)} hook with #{unquote(length(args))} arity"
end
def unquote("hook_#{name}" |> String.to_atom)(unquote_splicing(args)) when unquote(guard) do
unquote(body)
end
end
end
defmacro defhook({ name, _, args }, do: body) do
quote do
unless Enum.find @hooks, fn { name, arity } ->
name == unquote(name) and arity == unquote(length(args))
end do
raise ArgumentError, message: "unknown #{unquote(name)} hook with #{unquote(length(args))} arity"
end
def unquote("hook_#{name}" |> String.to_atom)(unquote_splicing(args)) do
unquote(body)
end
end
end
end