Current section

Files

Jump to
nuamnesia lib amnesia hooks.ex
Raw

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 _ -> { :_, [], nil } end
quote do
def unquote("hook_#{name}" |> String.to_atom)(unquote_splicing(args)) do
:undefined
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