Packages

Library bringing types support to elixir. Allows type validation in compile time.

Current section

Files

Jump to
tyx lib tyx.ex
Raw

lib/tyx.ex

defmodule Tyx do
@moduledoc """
`Tyx`
"""
# credo:disable-for-this-file Credo.Check.Warning.IoInspect
use Boundary
alias Tyx.Typemap
defmacro __using__(_opts) do
quote do
Module.register_attribute(__MODULE__, :tyx_annotation, accumulate: false)
Module.register_attribute(__MODULE__, :tyx, accumulate: true)
@on_definition Tyx.Hooks
@before_compile Tyx.Hooks
import Tyx
end
end
defmacro deft({:~>>, meta, [{fun, fmeta, args}, ret]}, body) do
[
extract_module_attribute(fun, args, ret, body, __CALLER__),
{:def, meta, [{fun, fmeta, untype(args, __CALLER__.context)}, body]}
]
end
defmacro deft({:when, gmeta, [{:~>>, meta, [{fun, fmeta, args}, ret]}, guards]}, body) do
[
extract_module_attribute(fun, args, ret, body, __CALLER__),
{:def, meta,
[{:when, gmeta, [{fun, fmeta, untype(args, __CALLER__.context)}, guards]}, body]}
]
end
defp extract_module_attribute(fun, args, ret, _body, ctx) do
args = for {:~>, _, [{arg, _, nil}, type]} <- args, do: {arg, Macro.expand(type, ctx)}
ret = Macro.expand(ret, ctx)
args_spec = for {_arg, type} <- args, do: Typemap.to_spec(type)
ret_spec = Typemap.to_spec(ret)
quote do
@tyx_annotation [<~: unquote(args), ~>: unquote(ret)]
@spec unquote(fun)(unquote_splicing(args_spec)) :: unquote(ret_spec)
end
end
defp untype(args, ctx) do
for {:~>, _, [{arg, _, nil}, _]} <- args, do: Macro.var(arg, ctx)
end
# defmacro left ~> right do
# IO.inspect({left, right}, label: "~>")
# :ok
# end
end