Current section
Files
Jump to
Current section
Files
src/doctest_forms.erl
%%%---------------------------------------------------------------------
%%% Copyright 2024 William Fank Thomé
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
%%%---------------------------------------------------------------------
-module(doctest_forms).
% API functions
-export([ module/1
, filename/1
, lookup_attribute/2
, get_attributes/2
, prepend/2
, append/2
]).
%%%=====================================================================
%%% API functions
%%%=====================================================================
module(Forms) ->
{ok, {_Ln, Mod}} = lookup_attribute(module, Forms),
Mod.
filename(Forms) ->
{ok, {_Ln, Filename}} = lookup_attribute(file, Forms),
Filename.
lookup_attribute(Name, Forms) ->
do_lookup_attribute(Forms, Name).
get_attributes(Name, Forms) ->
lists:flatten(filtermap(
fun(Type) -> Type =:= attribute end,
fun({attribute, Attr}) ->
case attribute_name(Attr) =:= Name of
true ->
{true, normalize_attributes(Attr)};
false ->
false
end
end,
Forms
)).
prepend(NewForms, Forms) when is_list(NewForms), is_list(Forms) ->
do_prepend(Forms, NewForms);
prepend(NewForm, Forms) when is_tuple(NewForm) ->
prepend([NewForm], Forms).
append(NewForms, Forms) when is_list(NewForms), is_list(Forms) ->
do_append(Forms, NewForms);
append(NewForm, Forms) when is_tuple(NewForm) ->
append([NewForm], Forms).
%%%=====================================================================
%%% Internal functions
%%%=====================================================================
do_lookup_attribute([Form | Forms], Name) ->
case is_attribute(Form) andalso attribute_name(Form) =:= Name of
true ->
{ok, hd(normalize_attributes(Form))};
false ->
do_lookup_attribute(Forms, Name)
end;
do_lookup_attribute([], _Name) ->
error.
filtermap(Validate, Filtermap, Forms) when
is_function(Validate, 1), is_function(Filtermap, 1), is_list(Forms) ->
lists:filtermap(fun(Form) ->
Type = erl_syntax:type(Form),
case Validate(Type) of
true ->
Filtermap({Type, Form});
false ->
false
end
end, Forms).
is_attribute(Form) ->
erl_syntax:type(Form) =:= attribute.
attribute_name(Form) ->
erl_syntax:atom_value(erl_syntax:attribute_name(Form)).
normalize_attributes(Form) ->
Exprs = erl_syntax:revert_forms(erl_syntax:attribute_arguments(Form)),
lists:map(fun(Expr) ->
{value, Value, []} = erl_eval:expr(Expr, []),
{line(Expr), Value}
end, Exprs).
line(Form) ->
erl_anno:line(erl_syntax:get_pos(Form)).
do_prepend([Form | Forms], NewForms) ->
case erl_syntax:type(Form) of
function ->
NewForms ++ [Form | Forms];
_ ->
[Form | do_prepend(Forms, NewForms)]
end;
do_prepend([], _NewForms) ->
[].
do_append([Form | Forms], NewForms) ->
case erl_syntax:type(Form) of
eof_marker ->
NewForms ++ [Form | Forms];
_ ->
[Form | do_append(Forms, NewForms)]
end;
do_append([], _NewForms) ->
[].