Current section

Files

Jump to
vela lib macros.ex
Raw

lib/macros.ex

defmodule Vela.Macros do
@moduledoc false
alias Vela.Stubs
def make_arity_2(f) when is_function(f, 1),
do: fn _serie, value -> f.(value) end
def make_arity_2(f) when is_function(f, 2),
do: f
defmacro use_config(opts) do
quote do
Enum.map(unquote(opts), fn {serie, vela} ->
vela =
vela
|> Keyword.put_new(:sorter, &Stubs.sort/2)
|> Keyword.put_new(:compare_by, &Stubs.itself/1)
|> Keyword.put_new(:comparator, &Stubs.compare/2)
|> Keyword.put_new(:corrector, &Stubs.correct/3)
|> Keyword.put_new(:threshold, nil)
|> Keyword.update(:validator, &Stubs.validate/1, fn existing ->
case existing do
fun when is_function(fun, 1) or is_function(fun, 2) -> fun
m when is_atom(m) -> &m.valid?/2
other -> raise Vela.AccessError, field: :validator
end
end)
{serie, vela}
end)
end
end
def use_types(extra_types) when is_list(extra_types) do
extra_types =
Enum.map(extra_types, fn
{k, nil} ->
{k, [{{:., [], [{:__aliases__, [alias: false], [:Vela]}, :value]}, [], []}]}
{k, type} when is_atom(type) ->
{k, {type, [], []}}
{k, {{_, _, _} = module, type}} ->
{k, {{:., [], [module, type]}, [], []}}
{k, {module, type}} when is_atom(module) and is_atom(type) ->
modules = module |> Module.split() |> Enum.map(&:"#{&1}")
{k, {{:., [], [{:__aliases__, [alias: false], modules}, type]}, [], []}}
{k, v} ->
{k, v}
end)
{:%{}, [],
[
{:__struct__, {:__MODULE__, [], Elixir}},
{:__errors__,
[
{{:., [], [{:__aliases__, [alias: false], [:Vela]}, :kv]}, [], []}
]},
{:__meta__, {:keyword, [], []}}
| extra_types
]}
end
defmacro main_ast do
quote do
@doc "Returns the list of series declared on #{__MODULE__}"
@spec series :: [Vela.serie()]
def series, do: @fields_ordered
@doc "Returns the config #{__MODULE__} was declared with"
@spec config :: [{atom(), Vela.options()}]
def config, do: @config
@doc "Returns the config for the serie `serie`, #{__MODULE__} was declared with"
@spec config(Vela.serie()) :: Vela.options()
def config(serie), do: @config[serie]
@doc "Returns the config value for the serie `serie`, #{__MODULE__} was declared with, and key"
@spec config(Vela.serie(), key :: atom(), default :: any()) :: Vela.option()
def config(serie, key, default \\ nil), do: Keyword.get(@config[serie], key, default)
use Vela.Access, @config
@behaviour Vela
@impl Vela
def slice(vela),
do: for({serie, [h | _]} <- vela, do: {serie, h})
@impl Vela
def purge(%__MODULE__{} = vela, validator \\ nil),
do: Vela.purge(vela, validator)
@impl Vela
def delta(%__MODULE__{} = vela, comparator \\ nil),
do: Vela.δ(vela, comparator)
@impl Vela
def equal?(%__MODULE__{} = v1, %__MODULE__{} = v2),
do: Vela.equal?(v1, v2)
end
end
end