-module(bristow_transform). -export([parse_transform/2]). parse_transform(Forms, _Options) -> {Alias, Forms1} = gen_alias(Forms), export_alias(Forms1, Alias). gen_alias(Forms) -> gen_alias(Forms, {}, [], []). gen_alias([], _, Alias, Acc) -> {Alias, lists:reverse(Acc)}; gen_alias([{function, _, Name, _, [{clause, _, Args, _, _}|_]} = Fun|Rest], _, Alias, Acc) -> gen_alias(Rest, {Name, Args}, Alias, [Fun|Acc]); gen_alias([{attribute, N, alias, Name}|Rest], {Fun, Args}, Alias, Acc) -> gen_alias(Rest, {Fun, Args}, [{Name, length(Args)}|Alias], [{function, N, Name, length(Args), [{clause, N, Args, [], [{call, N, {atom, 1, Fun}, Args}]}]}|Acc]); gen_alias([{attribute, _, alias, _}|_], {}, _, _) -> erlang:throw("-alias must follow a function definition"); gen_alias([Def|Rest], _, Alias, Acc) -> gen_alias(Rest, {}, Alias, [Def|Acc]). export_alias(Forms, Alias) -> {_, Forms1} = lists:foldl(fun ({attribute, N, export, Exports}, {A, Acc}) -> {[], [{attribute, N, export, Exports ++ A}|Acc]}; (Other, {A, Acc}) -> {A, [Other|Acc]} end, {Alias, []}, Forms), lists:reverse(Forms1).