Current section

Files

Jump to
defused lib module.ex
Raw

lib/module.ex

defmodule Defused.Module do
defmacro __using__(opts) do
quote do
fuse = Keyword.fetch!(unquote(opts), :fuse)
only = case Keyword.get(unquote(opts), :only, nil) do
nil -> nil
x -> MapSet.new(x)
end
except = case Keyword.get(unquote(opts), :except, nil) do
nil -> nil
x -> MapSet.new(x)
end
if only && except do
throw "Cannot specify both `only` and `except`"
end
use Defused
import Kernel, except: [def: 2]
import Defused.Module
@defused_only only
@defused_except except
end
end
defp meta(call) do
case call do
{:when, _, [call | _]} -> meta(call)
{name, _, args} ->
arity = case args do
nil -> 0
args -> length(args)
end
{name, arity}
end
end
defmacro def(call, expr \\ nil) do
quote do
{name, arity} = unquote(meta(call))
cond do
{name, arity} == {:blown_error, 2} -> Kernel.def(unquote(call), unquote(expr))
@defused_only != nil ->
case MapSet.member?(@defused_only, {name, arity}) do
false -> Kernel.def(unquote(call), unquote(expr))
true -> defused @fuse, unquote(call), unquote(expr)
end
@defused_except != nil ->
case MapSet.member?(@defused_except, {name, arity}) do
true -> Kernel.def(unquote(call), unquote(expr))
false -> defused @fuse, unquote(call), unquote(expr)
end
true -> defused @fuse, unquote(call), unquote(expr)
end
end
end
end