summaryrefslogtreecommitdiffstats
path: root/src/horse_autoexport.erl
blob: 6e4a49a72bd94795d2c5d238827328e67bf79e11 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
%% Copyright (c) 2013, Loïc Hoguin <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
%% copyright notice and this permission notice appear in all copies.
%%
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

-module(horse_autoexport).

-export([parse_transform/2]).

parse_transform([File, Module|Forms], _) ->
	Exports = [F || {attribute, _, export, [{F, 0}]} <- Forms],
	AutoExports = [{attribute, 0, export, [{F, 0}]}
		|| {function, _, F, 0, _} <- Forms,
			"horse_" =:= string:substr(atom_to_list(F), 1, 6),
			false =:= lists:member(F, Exports)],
	replace_calls([File, Module|AutoExports ++ Forms]).

replace_calls(Forms) ->
	lists:flatten([replace_call(Form) || Form <- Forms]).

replace_call(
	{function, Fu, Name, 0, [
		{clause, Cl, [], [], [
			{call, Ca, {remote, _, {atom, _, horse}, {atom, _, repeat}}, [
				Repeat,
				Expr
			]}
		]}
	]}
) when Repeat > 0 ->
	GenName = list_to_atom("generated_" ++ atom_to_list(Name)),
	[
		{function, Fu, Name, 0, [
			{clause, Cl, [], [], [
				{call, Ca, {atom, Ca, GenName}, [Repeat]}
			]}
		]},
		{function, Ca, GenName, 1, [
			{clause, Ca, [{integer, Ca, 0}], [], [
				{atom, Ca, ok}
			]},
			{clause, Ca, [{var, Ca, 'N'}], [], [
				Expr,
				{call, Ca, {atom, Ca, GenName}, [
					{op, Ca, '-', {var, Ca, 'N'}, {integer, Ca, 1}}
				]}
			]}
		]}
	];
replace_call(Form) ->
	Form.