Last active
February 24, 2016 22:22
-
-
Save doomspork/8f0d72dc1373f5a7448d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Concoct do | |
@alphabet "abcdefghijklmnopqrstuvwxyx" | |
@reserved ~w(init module_info)a | |
defmacro __using__(mod, _opts \\ []) do | |
wrappers = mod.module_info | |
|> Keyword.get(:exports) | |
|> Enum.filter(&Concoct.reserved_fun/1) | |
|> Enum.map(&Concoct.wrap_erl_fun/1) | |
quote do | |
@erl_mod unquote(mod) | |
unquote_splicing(wrappers) | |
end | |
end | |
def reserved_fun({name, _arity}) when name in @reserved do | |
false | |
end | |
def reserved_fun(_), do: true | |
def wrap_erl_fun({name, arity}) do | |
arity = if arity == 0, do: 0, else: arity - 1 | |
args = Enum.map(0..arity, &Concoct.gen_arg_name/1) | |
[sub|rem] = args | |
erl_args = rem ++ [sub] | |
quote do | |
def unquote(name)(unquote_splicing(args)) do | |
@erl_mod.unquote(name)(unquote_splicing(erl_args)) | |
end | |
end | |
end | |
def gen_arg_name(count) when count <= 25 do | |
atom = @alphabet | |
|> String.at(count) | |
|> String.to_atom | |
{atom, [], Elixir} | |
end | |
def gen_arg_name(count) do | |
count | |
|> Integer.to_string | |
|> String.split("", trim: true) | |
|> Enum.map(&Concoct.gen_arg_name/1) | |
|> Enum.join | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ConcoctTest do | |
use ExUnit.Case | |
doctest Concoct | |
defmodule Queue do | |
use Concoct, :queue | |
end | |
setup do | |
queue = :queue.new | |
{:ok, %{queue: queue}} | |
end | |
test "wraps simple functions", %{queue: queue} do | |
assert Queue.len(queue) == 0 | |
end | |
test "moves subject for Elixir piping", %{queue: queue} do | |
len = queue | |
|> Queue.in("Hi") | |
|> Queue.len | |
assert len == 1 | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i can has plz ;_;