%%% vim:ts=2:sw=2:et %%%----------------------------------------------------------------------------- %%% @doc Creation of module aliases %%% %%% @author Serge Aleynikov %%% @copyright 2021 Serge Aleynikov %%% @end %%%----------------------------------------------------------------------------- %%% Created 2021-06-01 %%%----------------------------------------------------------------------------- -module(alias). -export([create/2, create/3]). %% @doc Create a module `Alias' for the given `OrigMod' module. %% This function is useful for creating in-memory Elixir wrapper modules without %% needing to maintain persistent files with such wrappers. %% `IncFuns' argument can be `all' or a list of `{Fun, Arity}' values which %% only export a subset of functions from the `OrigMod'. create(Alias, OrigMod) -> create(Alias, OrigMod, all). create(Alias, OrigMod, IncFuns) when IncFuns == all; is_list(IncFuns) -> Exports = [T || T <- OrigMod:module_info(exports) , element(1, T) /= module_info , IncFuns==all orelse lists:member(T, IncFuns)], AST = [{attribute, ?LINE, module, Alias} ,{attribute, ?LINE, export, Exports} |[begin % AST of a function call from the OrigMod module Remote = {remote, ?LINE, {atom, ?LINE, OrigMod}, {atom, ?LINE, Fun}}, Args = [{var, ?LINE, list_to_atom("A" ++ integer_to_list(N))} || N <- lists:seq(1, Arity)], {function, ?LINE, Fun, Arity, [{clause, ?LINE, Args, [], [{call, ?LINE, Remote, Args}]}]} end || {Fun, Arity} <- Exports] ], {ok, Alias, Bin} = compile:forms(AST), {module, Alias} = code:load_binary(Alias, "/dev/null", Bin), {ok, Alias}.