Current section
Files
Jump to
Current section
Files
lib/oops.ex
defmodule Oops do
alias Oops.Modules
@default_properties [:value]
defmacro __using__(opts) do
modules = opts[:like] |> Modules.normalize
properties = opts[:properties] || @default_properties
[constructor(properties)] ++ getters(properties) ++ methods(modules)
end
defmacro defm(name, do: body) do
quote do
def unquote(name)(var!(this)) do
unquote(body)
end
end
end
defp constructor(properties) do
vars = properties |> length |> generate_vars
quote do
import Oops
def new(unquote_splicing(vars)), do: {__MODULE__, unquote_splicing(vars)}
end
end
defp getters(properties) do
for {property, index} <- Enum.with_index(properties) do
quote do
def unquote(property)(data) do
elem(data, unquote(index)+1)
end
end
end
end
defp methods([]), do: []
defp methods(modules) do
for module <- modules, {name, arity} <- module.__info__(:functions) do
vars = generate_vars(arity-1)
quote do
def unquote(name)(unquote_splicing(vars), {__MODULE__, value}) do
{__MODULE__, unquote(module).unquote(name)(value, unquote_splicing(vars))}
end
end
end
end
defp generate_vars(0), do: []
defp generate_vars(count) do
for index <- 1..count, do: Macro.var(:"var#{index}", __MODULE__)
end
end