Current section

Files

Jump to
erldist_filter lib edf.ex
Raw

lib/edf.ex

defmodule EDF do
require Record
records =
:lists.usort(
EDF.RecordExtractor.extract_all(from_lib: "erldist_filter/include/erldist_filter.hrl") ++
EDF.RecordExtractor.extract_all(from_lib: "erldist_filter/include/udist.hrl")
)
for {record, %{fields: fields}} <- records do
Record.defrecord(record, fields)
end
[record_guards0, record_guards1 | record_guards_rest] =
for {record, %{fields: fields}} <- records, into: [] do
record_size = length(fields) + 1
quote do
Record.is_record(var!(data), unquote(record)) and tuple_size(var!(data)) === unquote(record_size)
end
end
record_guards_init =
quote do
unquote(record_guards0) or unquote(record_guards1)
end
record_guards =
:lists.foldl(
fn record_guard, acc ->
quote do
unquote(acc) or unquote(record_guard)
end
end,
record_guards_init,
record_guards_rest
)
defguardp _is_record_type(data) when unquote(record_guards)
for {record, %{types: types}} <- records, into: [] do
@type unquote(record)() :: record(unquote(record), unquote(types))
end
[record_types0, record_types1 | record_types_rest] =
for {record, _definition} <- :lists.reverse(records), into: [] do
quote do
unquote(record)()
end
end
record_types_init =
quote do
unquote(record_types1) | unquote(record_types0)
end
record_types =
:lists.foldl(
fn record_type, acc ->
quote do
unquote(record_type) | unquote(acc)
end
end,
record_types_init,
record_types_rest
)
@type t() :: unquote(record_types)
defmodule Pretty do
@type t() :: %__MODULE__{
name: atom(),
pairs: Keyword.t()
}
@enforce_keys [:name, :pairs]
defstruct [:name, :pairs]
for {record, %{fields: fields}} <- records do
keys = :lists.map(&elem(&1, 0), fields)
vals = :lists.map(&{&1, [], nil}, keys)
pairs = :lists.zip(keys, vals)
def cast({unquote(record), unquote_splicing(vals)}) do
%__MODULE__{name: unquote(record), pairs: [unquote_splicing(pairs)]}
end
end
@spec inspect(term(), opts :: Inspect.Opts.t()) :: Inspect.Algebra.t()
def inspect(term, opts = %Inspect.Opts{}) do
{opts, inspect_fun} = inspect_opts(opts)
if EDF.is_record_type(term) do
inspect_fun.(cast(term), opts)
else
inspect_fun.(term, opts)
end
end
@spec inspect_opts(opts) :: {opts, (term(), opts -> Inspect.Algebra.t())} when opts: Inspect.Opts.t()
def inspect_opts(opts = %Inspect.Opts{}) do
case Keyword.get(opts.custom_options, __MODULE__) do
nil ->
inspect_fun = maybe_break_infinite_loop(opts.inspect_fun)
{%Inspect.Opts{
opts
| custom_options: Keyword.put(opts.custom_options, __MODULE__, inspect_fun),
inspect_fun: &__MODULE__.inspect/2
}, inspect_fun}
inspect_fun when is_function(inspect_fun, 2) ->
{opts, maybe_break_infinite_loop(inspect_fun)}
end
end
defp maybe_break_infinite_loop(inspect_fun) when is_function(inspect_fun, 2) do
case &__MODULE__.inspect/2 do
^inspect_fun ->
Inspect.Opts.default_inspect_fun()
_ ->
inspect_fun
end
end
end
defimpl Inspect, for: Pretty do
@impl true
def inspect(%Pretty{name: name, pairs: pairs}, opts) do
open = Inspect.Algebra.color("EDF." <> to_string(name) <> "(", :map, opts)
sep = Inspect.Algebra.color(",", :map, opts)
close = Inspect.Algebra.color(")", :map, opts)
fun = &Inspect.List.keyword/2
Inspect.Algebra.container_doc(open, pairs, close, opts, fun, separator: sep, break: :strict)
end
end
@spec inspect(Inspect.t(), keyword()) :: String.t()
def inspect(term, opts \\ []) do
{opts, _inspect_fun} = Pretty.inspect_opts(Inspect.Opts.new(opts))
opts = Map.to_list(Map.from_struct(opts))
Kernel.inspect(term, opts)
end
@spec is_record_type(term()) :: boolean()
def is_record_type(term) when _is_record_type(term) do
true
end
def is_record_type(_) do
false
end
@spec record_definitions :: [%{fields: [atom()], kind: :defrecord, name: atom(), tag: atom()}, ...]
def record_definitions() do
@__records__
end
end