mirror of
https://github.com/valitydev/parse_trans.git
synced 2024-11-06 00:25:16 +00:00
change license to Apache 2.0, whitespace cleanup
This commit is contained in:
parent
3958b77119
commit
ffc89ef491
178
LICENSE
Normal file
178
LICENSE
Normal file
@ -0,0 +1,178 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
40
rebar.config
40
rebar.config
@ -1,12 +1,36 @@
|
||||
%% -*- erlang -*-
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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.
|
||||
%% --------------------------------------------------
|
||||
|
||||
{erl_first_files, ["src/parse_trans.erl",
|
||||
"src/parse_trans_pp.erl",
|
||||
"src/parse_trans_codegen.erl"]}.
|
||||
"src/parse_trans_pp.erl",
|
||||
"src/parse_trans_codegen.erl"]}.
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
{xref_checks, [undefined_function_calls]}.
|
||||
{deps, [{edown, ".*", {git, "git://github.com/uwiger/edown.git", {branch, "master"}}}]}.
|
||||
{edoc_opts, [{doclet, edown_doclet},
|
||||
{top_level_readme,
|
||||
{"./README.md",
|
||||
"http://github.com/uwiger/parse_trans"}}]}.
|
||||
|
||||
{profiles,
|
||||
[{docs,
|
||||
[
|
||||
{deps,
|
||||
[{edown, ".*",
|
||||
{git, "git://github.com/uwiger/edown.git", {tag, "0.8"}}}]},
|
||||
{edoc_opts, [{doclet, edown_doclet},
|
||||
{top_level_readme,
|
||||
{"./README.md",
|
||||
"http://github.com/uwiger/parse_trans"}}]}
|
||||
]}
|
||||
]}.
|
||||
|
@ -1,28 +1,23 @@
|
||||
%%% The contents of this file are subject to the Erlang Public License,
|
||||
%%% Version 1.1, (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.erlang.org/EPLICENSE
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and limitations
|
||||
%% 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.
|
||||
%%
|
||||
%% The Original Code is exprecs-0.2.
|
||||
%%
|
||||
%% The Initial Developer of the Original Code is Ericsson AB.
|
||||
%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
||||
%% All Rights Reserved.
|
||||
%%
|
||||
%% Contributor(s): ______________________________________.
|
||||
|
||||
%%-------------------------------------------------------------------
|
||||
%% --------------------------------------------------
|
||||
%% File : ct_expand.erl
|
||||
%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
||||
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||
%% @end
|
||||
%% Description :
|
||||
%%
|
||||
%% Created : 7 Apr 2010 by Ulf Wiger <ulf@feuerlabs.com>
|
||||
%% Created : 7 Apr 2010 by Ulf Wiger <ulf@wiger.net>
|
||||
%%-------------------------------------------------------------------
|
||||
|
||||
%% @doc Compile-time expansion utility
|
||||
@ -53,7 +48,7 @@
|
||||
-export([parse_transform/2]).
|
||||
|
||||
-export([extract_fun/3,
|
||||
lfun_rewrite/2]).
|
||||
lfun_rewrite/2]).
|
||||
|
||||
-type form() :: any().
|
||||
-type forms() :: [form()].
|
||||
@ -65,37 +60,37 @@
|
||||
parse_transform(Forms, Options) ->
|
||||
Trace = ct_trace_opt(Options, Forms),
|
||||
case parse_trans:depth_first(fun(T,F,C,A) ->
|
||||
xform_fun(T,F,C,A,Forms, Trace)
|
||||
end, [], Forms, Options) of
|
||||
{error, Es} ->
|
||||
Es ++ Forms;
|
||||
{NewForms, _} ->
|
||||
parse_trans:revert(NewForms)
|
||||
xform_fun(T,F,C,A,Forms, Trace)
|
||||
end, [], Forms, Options) of
|
||||
{error, Es} ->
|
||||
Es ++ Forms;
|
||||
{NewForms, _} ->
|
||||
parse_trans:revert(NewForms)
|
||||
end.
|
||||
|
||||
ct_trace_opt(Options, Forms) ->
|
||||
case proplists:get_value(ct_expand_trace, Options) of
|
||||
undefined ->
|
||||
case [Opt || {attribute,_,ct_expand_trace,Opt} <- Forms] of
|
||||
[] ->
|
||||
[];
|
||||
[_|_] = L ->
|
||||
lists:last(L)
|
||||
end;
|
||||
Flags when is_list(Flags) ->
|
||||
Flags
|
||||
undefined ->
|
||||
case [Opt || {attribute,_,ct_expand_trace,Opt} <- Forms] of
|
||||
[] ->
|
||||
[];
|
||||
[_|_] = L ->
|
||||
lists:last(L)
|
||||
end;
|
||||
Flags when is_list(Flags) ->
|
||||
Flags
|
||||
end.
|
||||
|
||||
xform_fun(application, Form, _Ctxt, Acc, Forms, Trace) ->
|
||||
MFA = erl_syntax_lib:analyze_application(Form),
|
||||
case MFA of
|
||||
{?MODULE, {term, 1}} ->
|
||||
LFH = fun(Name, Args, Bs) ->
|
||||
eval_lfun(
|
||||
extract_fun(Name, length(Args), Forms),
|
||||
Args, Bs, Forms, Trace)
|
||||
end,
|
||||
Args = erl_syntax:application_arguments(Form),
|
||||
LFH = fun(Name, Args, Bs) ->
|
||||
eval_lfun(
|
||||
extract_fun(Name, length(Args), Forms),
|
||||
Args, Bs, Forms, Trace)
|
||||
end,
|
||||
Args = erl_syntax:application_arguments(Form),
|
||||
RevArgs = parse_trans:revert(Args),
|
||||
case erl_eval:exprs(RevArgs, [], {eval, LFH}) of
|
||||
{value, Value,[]} ->
|
||||
@ -113,43 +108,43 @@ xform_fun(_, Form, _Ctxt, Acc, _, _) ->
|
||||
|
||||
extract_fun(Name, Arity, Forms) ->
|
||||
case [F_ || {function,_,N_,A_,_Cs} = F_ <- Forms,
|
||||
N_ == Name, A_ == Arity] of
|
||||
[] ->
|
||||
erlang:error({undef, [{Name, Arity}]});
|
||||
[FForm] ->
|
||||
FForm
|
||||
N_ == Name, A_ == Arity] of
|
||||
[] ->
|
||||
erlang:error({undef, [{Name, Arity}]});
|
||||
[FForm] ->
|
||||
FForm
|
||||
end.
|
||||
|
||||
eval_lfun({function,L,F,_,Clauses}, Args, Bs, Forms, Trace) ->
|
||||
try
|
||||
begin
|
||||
{ArgsV, Bs1} = lists:mapfoldl(
|
||||
fun(A, Bs_) ->
|
||||
{value,AV,Bs1_} =
|
||||
erl_eval:expr(A, Bs_, lfh(Forms, Trace)),
|
||||
{abstract(AV), Bs1_}
|
||||
end, Bs, Args),
|
||||
Expr = {call, L, {'fun', L, {clauses, lfun_rewrite(Clauses, Forms)}}, ArgsV},
|
||||
call_trace(Trace =/= [], L, F, ArgsV),
|
||||
{value, Ret, _} =
|
||||
erl_eval:expr(Expr, erl_eval:new_bindings(), lfh(Forms, Trace)),
|
||||
ret_trace(lists:member(r, Trace) orelse lists:member(x, Trace),
|
||||
L, F, Args, Ret),
|
||||
%% restore bindings
|
||||
{value, Ret, Bs1}
|
||||
end
|
||||
begin
|
||||
{ArgsV, Bs1} = lists:mapfoldl(
|
||||
fun(A, Bs_) ->
|
||||
{value,AV,Bs1_} =
|
||||
erl_eval:expr(A, Bs_, lfh(Forms, Trace)),
|
||||
{abstract(AV), Bs1_}
|
||||
end, Bs, Args),
|
||||
Expr = {call, L, {'fun', L, {clauses, lfun_rewrite(Clauses, Forms)}}, ArgsV},
|
||||
call_trace(Trace =/= [], L, F, ArgsV),
|
||||
{value, Ret, _} =
|
||||
erl_eval:expr(Expr, erl_eval:new_bindings(), lfh(Forms, Trace)),
|
||||
ret_trace(lists:member(r, Trace) orelse lists:member(x, Trace),
|
||||
L, F, Args, Ret),
|
||||
%% restore bindings
|
||||
{value, Ret, Bs1}
|
||||
end
|
||||
catch
|
||||
error:Err ->
|
||||
exception_trace(lists:member(x, Trace), L, F, Args, Err),
|
||||
error(Err)
|
||||
error:Err ->
|
||||
exception_trace(lists:member(x, Trace), L, F, Args, Err),
|
||||
error(Err)
|
||||
end.
|
||||
|
||||
lfh(Forms, Trace) ->
|
||||
{eval, fun(Name, As, Bs1) ->
|
||||
eval_lfun(
|
||||
extract_fun(Name, length(As), Forms),
|
||||
As, Bs1, Forms, Trace)
|
||||
end}.
|
||||
eval_lfun(
|
||||
extract_fun(Name, length(As), Forms),
|
||||
As, Bs1, Forms, Trace)
|
||||
end}.
|
||||
|
||||
call_trace(false, _, _, _) -> ok;
|
||||
call_trace(true, L, F, As) ->
|
||||
@ -159,14 +154,14 @@ pp_function(F, []) ->
|
||||
atom_to_list(F) ++ "()";
|
||||
pp_function(F, [A|As]) ->
|
||||
lists:flatten([atom_to_list(F), "(",
|
||||
[io_lib:fwrite("~w", [erl_parse:normalise(A)]) |
|
||||
[[",", io_lib:fwrite("~w", [erl_parse:normalise(A_)])] || A_ <- As]],
|
||||
")"]).
|
||||
[io_lib:fwrite("~w", [erl_parse:normalise(A)]) |
|
||||
[[",", io_lib:fwrite("~w", [erl_parse:normalise(A_)])] || A_ <- As]],
|
||||
")"]).
|
||||
|
||||
ret_trace(false, _, _, _, _) -> ok;
|
||||
ret_trace(true, L, F, Args, Res) ->
|
||||
io:fwrite("ct_expand (~w): returned from ~w/~w: ~w~n",
|
||||
[L, F, length(Args), Res]).
|
||||
[L, F, length(Args), Res]).
|
||||
|
||||
exception_trace(false, _, _, _, _) -> ok;
|
||||
exception_trace(true, L, F, Args, Err) ->
|
||||
@ -176,10 +171,10 @@ exception_trace(true, L, F, Args, Err) ->
|
||||
lfun_rewrite(Exprs, Forms) ->
|
||||
parse_trans:plain_transform(
|
||||
fun({'fun',L,{function,F,A}}) ->
|
||||
{function,_,_,_,Cs} = extract_fun(F, A, Forms),
|
||||
{'fun',L,{clauses, Cs}};
|
||||
(_) ->
|
||||
continue
|
||||
{function,_,_,_,Cs} = extract_fun(F, A, Forms),
|
||||
{'fun',L,{clauses, Cs}};
|
||||
(_) ->
|
||||
continue
|
||||
end, Exprs).
|
||||
|
||||
|
||||
@ -190,15 +185,15 @@ lfun_rewrite(Exprs, Forms) ->
|
||||
AbsTerm :: abstract_expr().
|
||||
abstract(T) when is_function(T) ->
|
||||
case erlang:fun_info(T, module) of
|
||||
{module, erl_eval} ->
|
||||
case erl_eval:fun_data(T) of
|
||||
{fun_data, _Imports, Clauses} ->
|
||||
{'fun', 0, {clauses, Clauses}};
|
||||
false ->
|
||||
erlang:error(function_clause) % mimicking erl_parse:abstract(T)
|
||||
end;
|
||||
_ ->
|
||||
erlang:error(function_clause)
|
||||
{module, erl_eval} ->
|
||||
case erl_eval:fun_data(T) of
|
||||
{fun_data, _Imports, Clauses} ->
|
||||
{'fun', 0, {clauses, Clauses}};
|
||||
false ->
|
||||
erlang:error(function_clause) % mimicking erl_parse:abstract(T)
|
||||
end;
|
||||
_ ->
|
||||
erlang:error(function_clause)
|
||||
end;
|
||||
abstract(T) when is_integer(T) -> {integer,0,T};
|
||||
abstract(T) when is_float(T) -> {float,0,T};
|
||||
|
772
src/exprecs.erl
772
src/exprecs.erl
File diff suppressed because it is too large
Load Diff
@ -1,30 +1,32 @@
|
||||
%%% -*- erlang -*-
|
||||
%%% The contents of this file are subject to the Erlang Public License,
|
||||
%%% Version 1.1, (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.erlang.org/EPLICENSE
|
||||
%%%
|
||||
%%% Software distributed under the License is distributed on an "AS IS"
|
||||
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%%% the License for the specific language governing rights and limitations
|
||||
%%% under the License.
|
||||
%%%
|
||||
%%% The Original Code is exprecs-0.2.
|
||||
%%%
|
||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
||||
%%% All Rights Reserved.
|
||||
%%%
|
||||
%%% Contributor(s): ______________________________________.
|
||||
|
||||
%%% @author Ulf Wiger <ulf.wiger@feuerlabs.com>
|
||||
%%% @doc This is a container for parse_trans modules.
|
||||
%%% @end
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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.
|
||||
%% --------------------------------------------------
|
||||
%%
|
||||
%% @author Ulf Wiger <ulf@wiger.net>
|
||||
%% @doc Parse transform library.
|
||||
%% @end
|
||||
{application, parse_trans,
|
||||
[{description, "Parse transform library"},
|
||||
{vsn, git},
|
||||
{registered, []},
|
||||
{applications, [kernel, stdlib, syntax_tools]},
|
||||
{env, []}
|
||||
{env, []},
|
||||
|
||||
{maintainers, ["Ulf Wiger"]},
|
||||
{licenses, ["Apache 2.0"]},
|
||||
{links, [{"Github", "https://github.com/uwiger/parse_trans"}]}
|
||||
]}.
|
||||
|
||||
|
@ -1,35 +1,32 @@
|
||||
%%% The contents of this file are subject to the Erlang Public License,
|
||||
%%% Version 1.1, (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.erlang.org/EPLICENSE
|
||||
%%%
|
||||
%%% Software distributed under the License is distributed on an "AS IS"
|
||||
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%%% the License for the specific language governing rights and limitations
|
||||
%%% under the License.
|
||||
%%%
|
||||
%%% The Original Code is exprecs-0.2.
|
||||
%%%
|
||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
||||
%%% All Rights Reserved.
|
||||
%%%
|
||||
%%% Contributor(s): ______________________________________.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% File : parse_trans.erl
|
||||
%%% @author : Ulf Wiger <ulf.wiger@feuerlabs.com>
|
||||
%%% @end
|
||||
%%% Description :
|
||||
%%%
|
||||
%%% Created : 13 Feb 2006 by Ulf Wiger <ulf.wiger@feuerlabs.com> (then Ericsson)
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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.
|
||||
%% --------------------------------------------------
|
||||
%% File : parse_trans.erl
|
||||
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||
%% @end
|
||||
%% Description :
|
||||
%%
|
||||
%% Created : 13 Feb 2006 by Ulf Wiger <ulf@wiger.net> (then Ericsson)
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
%%% @doc Generic parse transform library for Erlang.
|
||||
%%%
|
||||
%%% <p>...</p>
|
||||
%%%
|
||||
%%% @end
|
||||
%% @doc Generic parse transform library for Erlang.
|
||||
%%
|
||||
%% <p>...</p>
|
||||
%%
|
||||
%% @end
|
||||
|
||||
-module(parse_trans).
|
||||
|
||||
@ -37,12 +34,12 @@
|
||||
|
||||
-export([
|
||||
inspect/4,
|
||||
transform/4,
|
||||
transform/4,
|
||||
depth_first/4,
|
||||
revert/1,
|
||||
revert_form/1,
|
||||
format_exception/2, format_exception/3,
|
||||
return/2
|
||||
revert_form/1,
|
||||
format_exception/2, format_exception/3,
|
||||
return/2
|
||||
]).
|
||||
|
||||
-export([
|
||||
@ -55,13 +52,13 @@
|
||||
do_inspect/4,
|
||||
do_transform/4,
|
||||
do_depth_first/4,
|
||||
top/3
|
||||
top/3
|
||||
]).
|
||||
|
||||
-export([do_insert_forms/4,
|
||||
replace_function/4,
|
||||
replace_function/5,
|
||||
export_function/3]).
|
||||
replace_function/4,
|
||||
replace_function/5,
|
||||
export_function/3]).
|
||||
|
||||
-export([
|
||||
context/2,
|
||||
@ -85,8 +82,8 @@
|
||||
]).
|
||||
|
||||
-record(context, {module,
|
||||
function,
|
||||
arity,
|
||||
function,
|
||||
arity,
|
||||
file,
|
||||
options}).
|
||||
|
||||
@ -97,7 +94,7 @@
|
||||
|
||||
-define(ERROR(R, F, I),
|
||||
begin
|
||||
Trace = erlang:get_stacktrace(),
|
||||
Trace = erlang:get_stacktrace(),
|
||||
rpt_error(R, F, I, Trace),
|
||||
throw({error,get_pos(I),{R, Trace}})
|
||||
end).
|
||||
@ -110,11 +107,11 @@
|
||||
-type options() :: [{atom(), any()}].
|
||||
-type type() :: atom().
|
||||
-type xform_f_rec() :: fun((type(), form(), #context{}, Acc) ->
|
||||
{form(), boolean(), Acc}
|
||||
| {forms(), form(), forms(), boolean(), Acc}).
|
||||
{form(), boolean(), Acc}
|
||||
| {forms(), form(), forms(), boolean(), Acc}).
|
||||
-type xform_f_df() :: fun((type(), form(), #context{}, Acc) ->
|
||||
{form(), Acc}
|
||||
| {forms(), form(), forms(), Acc}).
|
||||
{form(), Acc}
|
||||
| {forms(), form(), forms(), Acc}).
|
||||
-type insp_f() :: fun((type(), form(), #context{}, A) -> {boolean(), A}).
|
||||
|
||||
|
||||
@ -173,17 +170,17 @@ plain_transform1(_, []) ->
|
||||
[];
|
||||
plain_transform1(Fun, [F|Fs]) when is_atom(element(1,F)) ->
|
||||
case Fun(F) of
|
||||
skip ->
|
||||
plain_transform1(Fun, Fs);
|
||||
continue ->
|
||||
[list_to_tuple(plain_transform1(Fun, tuple_to_list(F))) |
|
||||
plain_transform1(Fun, Fs)];
|
||||
{done, NewF} ->
|
||||
[NewF | Fs];
|
||||
{error, Reason} ->
|
||||
error(Reason, F, [{form, F}]);
|
||||
NewF when is_tuple(NewF) ->
|
||||
[NewF | plain_transform1(Fun, Fs)]
|
||||
skip ->
|
||||
plain_transform1(Fun, Fs);
|
||||
continue ->
|
||||
[list_to_tuple(plain_transform1(Fun, tuple_to_list(F))) |
|
||||
plain_transform1(Fun, Fs)];
|
||||
{done, NewF} ->
|
||||
[NewF | Fs];
|
||||
{error, Reason} ->
|
||||
error(Reason, F, [{form, F}]);
|
||||
NewF when is_tuple(NewF) ->
|
||||
[NewF | plain_transform1(Fun, Fs)]
|
||||
end;
|
||||
plain_transform1(Fun, [L|Fs]) when is_list(L) ->
|
||||
[plain_transform1(Fun, L) | plain_transform1(Fun, Fs)];
|
||||
@ -204,10 +201,10 @@ plain_transform1(_, F) ->
|
||||
integer().
|
||||
get_pos(I) when is_list(I) ->
|
||||
case proplists:get_value(form, I) of
|
||||
undefined ->
|
||||
?DUMMY_LINE;
|
||||
Form ->
|
||||
erl_syntax:get_pos(Form)
|
||||
undefined ->
|
||||
?DUMMY_LINE;
|
||||
Form ->
|
||||
erl_syntax:get_pos(Form)
|
||||
end.
|
||||
|
||||
|
||||
@ -243,7 +240,7 @@ get_module(Forms) ->
|
||||
%%% @end
|
||||
%%%
|
||||
-spec get_attribute(atom(), [any()]) ->
|
||||
'none' | [erl_syntax:syntaxTree()].
|
||||
'none' | [erl_syntax:syntaxTree()].
|
||||
%%
|
||||
get_attribute(A, Forms) -> get_attribute(A,Forms,[erl_syntax:atom(undefined)]).
|
||||
get_attribute(A, Forms, Undef) ->
|
||||
@ -318,17 +315,17 @@ do(Transform, Fun, Acc, Forms, Options) ->
|
||||
Context = initial_context(Forms, Options),
|
||||
File = Context#context.file,
|
||||
try Transform(Fun, Acc, Forms, Context) of
|
||||
{NewForms, Acc1} when is_list(NewForms) ->
|
||||
NewForms1 = optionally_renumber(NewForms, Options),
|
||||
optionally_pretty_print(NewForms1, Options, Context),
|
||||
{NewForms1, Acc1}
|
||||
{NewForms, Acc1} when is_list(NewForms) ->
|
||||
NewForms1 = optionally_renumber(NewForms, Options),
|
||||
optionally_pretty_print(NewForms1, Options, Context),
|
||||
{NewForms1, Acc1}
|
||||
catch
|
||||
error:Reason ->
|
||||
{error,
|
||||
[{File, [{?DUMMY_LINE, ?MODULE,
|
||||
{Reason, erlang:get_stacktrace()}}]}]};
|
||||
throw:{error, Ln, What} ->
|
||||
{error, [{error, {Ln, ?MODULE, What}}]}
|
||||
error:Reason ->
|
||||
{error,
|
||||
[{File, [{?DUMMY_LINE, ?MODULE,
|
||||
{Reason, erlang:get_stacktrace()}}]}]};
|
||||
throw:{error, Ln, What} ->
|
||||
{error, [{error, {Ln, ?MODULE, What}}]}
|
||||
end.
|
||||
|
||||
-spec top(function(), forms(), list()) ->
|
||||
@ -337,18 +334,18 @@ top(F, Forms, Options) ->
|
||||
Context = initial_context(Forms, Options),
|
||||
File = Context#context.file,
|
||||
try F(Forms, Context) of
|
||||
{error, Reason} -> {error, Reason};
|
||||
NewForms when is_list(NewForms) ->
|
||||
NewForms1 = optionally_renumber(NewForms, Options),
|
||||
{error, Reason} -> {error, Reason};
|
||||
NewForms when is_list(NewForms) ->
|
||||
NewForms1 = optionally_renumber(NewForms, Options),
|
||||
optionally_pretty_print(NewForms1, Options, Context),
|
||||
NewForms1
|
||||
NewForms1
|
||||
catch
|
||||
error:Reason ->
|
||||
{error,
|
||||
[{File, [{?DUMMY_LINE, ?MODULE,
|
||||
{Reason, erlang:get_stacktrace()}}]}]};
|
||||
throw:{error, Ln, What} ->
|
||||
{error, [{File, [{Ln, ?MODULE, What}]}], []}
|
||||
throw:{error, Ln, What} ->
|
||||
{error, [{File, [{Ln, ?MODULE, What}]}], []}
|
||||
end.
|
||||
|
||||
replace_function(F, Arity, NewForm, Forms) ->
|
||||
@ -356,39 +353,39 @@ replace_function(F, Arity, NewForm, Forms) ->
|
||||
|
||||
replace_function(F, Arity, NewForm, Forms, Opts) ->
|
||||
{NewForms, _} =
|
||||
do_transform(
|
||||
fun(function, Form, _Ctxt, Acc) ->
|
||||
case erl_syntax:revert(Form) of
|
||||
{function, _, F, Arity, _} = RevForm ->
|
||||
{[], NewForm, with_original_f(RevForm, Opts),
|
||||
false, Acc};
|
||||
_ ->
|
||||
{Form, false, Acc}
|
||||
end;
|
||||
(_, Form, _Ctxt, Acc) ->
|
||||
{Form, false, Acc}
|
||||
end, false, Forms, initial_context(Forms, [])),
|
||||
do_transform(
|
||||
fun(function, Form, _Ctxt, Acc) ->
|
||||
case erl_syntax:revert(Form) of
|
||||
{function, _, F, Arity, _} = RevForm ->
|
||||
{[], NewForm, with_original_f(RevForm, Opts),
|
||||
false, Acc};
|
||||
_ ->
|
||||
{Form, false, Acc}
|
||||
end;
|
||||
(_, Form, _Ctxt, Acc) ->
|
||||
{Form, false, Acc}
|
||||
end, false, Forms, initial_context(Forms, [])),
|
||||
revert(maybe_export_renamed(NewForms, Arity, Opts)).
|
||||
|
||||
with_original_f({function,_,_,_,_} = Form, Opts) ->
|
||||
case lists:keyfind(rename_original, 1, Opts) of
|
||||
{_, NewName} when is_atom(NewName) ->
|
||||
[setelement(3, Form, NewName)];
|
||||
_ ->
|
||||
[]
|
||||
{_, NewName} when is_atom(NewName) ->
|
||||
[setelement(3, Form, NewName)];
|
||||
_ ->
|
||||
[]
|
||||
end.
|
||||
|
||||
maybe_export_renamed(Forms, Arity, Opts) ->
|
||||
case lists:keyfind(rename_original, 1, Opts) of
|
||||
{_, NewName} when is_atom(NewName) ->
|
||||
export_function(NewName, Arity, Forms);
|
||||
_ ->
|
||||
Forms
|
||||
{_, NewName} when is_atom(NewName) ->
|
||||
export_function(NewName, Arity, Forms);
|
||||
_ ->
|
||||
Forms
|
||||
end.
|
||||
|
||||
export_function(F, Arity, Forms) ->
|
||||
do_insert_forms(above, [{attribute, 1, export, [{F, Arity}]}], Forms,
|
||||
initial_context(Forms, [])).
|
||||
initial_context(Forms, [])).
|
||||
|
||||
-spec do_insert_forms(above | below, forms(), forms(), #context{}) ->
|
||||
forms().
|
||||
@ -420,12 +417,12 @@ optionally_pretty_print(Result, Options, Context) ->
|
||||
DoLFs = option_value(pt_log_forms, Options, Result),
|
||||
File = Context#context.file,
|
||||
if DoLFs ->
|
||||
Out1 = outfile(File, forms),
|
||||
{ok,Fd} = file:open(Out1, [write]),
|
||||
try lists:foreach(fun(F) -> io:fwrite(Fd, "~p.~n", [F]) end, Result)
|
||||
after
|
||||
ok = file:close(Fd)
|
||||
end;
|
||||
Out1 = outfile(File, forms),
|
||||
{ok,Fd} = file:open(Out1, [write]),
|
||||
try lists:foreach(fun(F) -> io:fwrite(Fd, "~p.~n", [F]) end, Result)
|
||||
after
|
||||
ok = file:close(Fd)
|
||||
end;
|
||||
true -> ok
|
||||
end,
|
||||
if DoPP ->
|
||||
@ -437,12 +434,12 @@ optionally_pretty_print(Result, Options, Context) ->
|
||||
|
||||
optionally_renumber(Result, Options) ->
|
||||
case option_value(pt_renumber, Options, Result) of
|
||||
true ->
|
||||
io:fwrite("renumbering...~n", []),
|
||||
Rev = revert(Result),
|
||||
renumber_(Rev);
|
||||
false ->
|
||||
Result
|
||||
true ->
|
||||
io:fwrite("renumbering...~n", []),
|
||||
Rev = revert(Result),
|
||||
renumber_(Rev);
|
||||
false ->
|
||||
Result
|
||||
end.
|
||||
|
||||
renumber_(L) when is_list(L) ->
|
||||
@ -453,15 +450,15 @@ renumber_(L, Acc) when is_list(L) ->
|
||||
lists:mapfoldl(fun renumber_/2, Acc, L);
|
||||
renumber_(T, Prev) when is_tuple(T) ->
|
||||
case is_form(T) of
|
||||
true ->
|
||||
New = Prev+1,
|
||||
T1 = setelement(2, T, New),
|
||||
{Res, NewAcc} = renumber_(tuple_to_list(T1), New),
|
||||
{list_to_tuple(Res), NewAcc};
|
||||
false ->
|
||||
L = tuple_to_list(T),
|
||||
{Res, NewAcc} = renumber_(L, Prev),
|
||||
{list_to_tuple(Res), NewAcc}
|
||||
true ->
|
||||
New = Prev+1,
|
||||
T1 = setelement(2, T, New),
|
||||
{Res, NewAcc} = renumber_(tuple_to_list(T1), New),
|
||||
{list_to_tuple(Res), NewAcc};
|
||||
false ->
|
||||
L = tuple_to_list(T),
|
||||
{Res, NewAcc} = renumber_(L, Prev),
|
||||
{list_to_tuple(Res), NewAcc}
|
||||
end;
|
||||
renumber_(X, Prev) ->
|
||||
{X, Prev}.
|
||||
@ -469,10 +466,10 @@ renumber_(X, Prev) ->
|
||||
is_form(T) when element(1,T)==type -> true;
|
||||
is_form(T) ->
|
||||
try erl_syntax:type(T),
|
||||
true
|
||||
true
|
||||
catch
|
||||
error:_ ->
|
||||
false
|
||||
error:_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
option_value(Key, Options, Result) ->
|
||||
@ -606,12 +603,12 @@ revert_form(F) ->
|
||||
|
||||
revert_form(F, W) ->
|
||||
case erl_syntax:revert(F) of
|
||||
{attribute,L,A,Tree} when element(1,Tree) == tree ->
|
||||
{attribute,L,A,erl_syntax:revert(Tree)};
|
||||
Result ->
|
||||
if W -> fix_impl_fun(Result);
|
||||
true -> Result
|
||||
end
|
||||
{attribute,L,A,Tree} when element(1,Tree) == tree ->
|
||||
{attribute,L,A,erl_syntax:revert(Tree)};
|
||||
Result ->
|
||||
if W -> fix_impl_fun(Result);
|
||||
true -> Result
|
||||
end
|
||||
end.
|
||||
|
||||
fix_impl_fun({'fun',L,{function,{atom,_,Fn},{integer,_,Ay}}}) ->
|
||||
@ -627,26 +624,26 @@ fix_impl_fun(X) ->
|
||||
|
||||
needs_revert_workaround() ->
|
||||
case application:get_env(parse_trans,revert_workaround) of
|
||||
{ok, Bool} when is_boolean(Bool) -> Bool;
|
||||
_ ->
|
||||
Res = try lint_reverted()
|
||||
catch
|
||||
error:_ ->
|
||||
true
|
||||
end,
|
||||
application:set_env(parse_trans,revert_workaround,Res),
|
||||
Res
|
||||
{ok, Bool} when is_boolean(Bool) -> Bool;
|
||||
_ ->
|
||||
Res = try lint_reverted()
|
||||
catch
|
||||
error:_ ->
|
||||
true
|
||||
end,
|
||||
application:set_env(parse_trans,revert_workaround,Res),
|
||||
Res
|
||||
end.
|
||||
|
||||
lint_reverted() ->
|
||||
Ts = [{attribute,1,module,m},
|
||||
{attribute,2,export,[{f,0}]},
|
||||
erl_syntax:function(erl_syntax:atom(f),
|
||||
[erl_syntax:clause(
|
||||
[],
|
||||
[erl_syntax:implicit_fun(
|
||||
erl_syntax:atom(f),
|
||||
erl_syntax:integer(0))])])],
|
||||
{attribute,2,export,[{f,0}]},
|
||||
erl_syntax:function(erl_syntax:atom(f),
|
||||
[erl_syntax:clause(
|
||||
[],
|
||||
[erl_syntax:implicit_fun(
|
||||
erl_syntax:atom(f),
|
||||
erl_syntax:integer(0))])])],
|
||||
Rev = erl_syntax:revert_forms(Ts),
|
||||
erl_lint:module(Rev),
|
||||
false.
|
||||
@ -675,23 +672,23 @@ lint_reverted() ->
|
||||
%%% @end
|
||||
return(Forms, Context) ->
|
||||
JustForms = plain_transform(
|
||||
fun({error,_}) -> skip;
|
||||
({warning,_}) -> skip;
|
||||
(_) -> continue
|
||||
end, Forms),
|
||||
fun({error,_}) -> skip;
|
||||
({warning,_}) -> skip;
|
||||
(_) -> continue
|
||||
end, Forms),
|
||||
File = case Context of
|
||||
#context{file = F} -> F;
|
||||
_ -> "parse_transform"
|
||||
end,
|
||||
#context{file = F} -> F;
|
||||
_ -> "parse_transform"
|
||||
end,
|
||||
case {find_forms(Forms, error), find_forms(Forms, warning)} of
|
||||
{[], []} ->
|
||||
JustForms;
|
||||
{[], Ws} ->
|
||||
{warnings, JustForms, [{File, [W || {warning,W} <- Ws]}]};
|
||||
{Es, Ws} ->
|
||||
{error,
|
||||
[{File, [E || {error,E} <- Es]}],
|
||||
[{File, [W || {warning,W} <- Ws]}]}
|
||||
{[], []} ->
|
||||
JustForms;
|
||||
{[], Ws} ->
|
||||
{warnings, JustForms, [{File, [W || {warning,W} <- Ws]}]};
|
||||
{Es, Ws} ->
|
||||
{error,
|
||||
[{File, [E || {error,E} <- Es]}],
|
||||
[{File, [W || {warning,W} <- Ws]}]}
|
||||
end.
|
||||
|
||||
find_forms([H|T], Tag) when element(1, H) == Tag ->
|
||||
@ -731,18 +728,18 @@ format_exception(Class, Reason) ->
|
||||
%%% @end
|
||||
format_exception(Class, Reason, Lines) ->
|
||||
PrintF = fun(Term, I) ->
|
||||
io_lib_pretty:print(
|
||||
Term, I, columns(), ?LINEMAX, ?CHAR_MAX,
|
||||
record_print_fun())
|
||||
end,
|
||||
io_lib_pretty:print(
|
||||
Term, I, columns(), ?LINEMAX, ?CHAR_MAX,
|
||||
record_print_fun())
|
||||
end,
|
||||
StackF = fun(_, _, _) -> false end,
|
||||
lines(Lines, lib:format_exception(
|
||||
1, Class, Reason, erlang:get_stacktrace(), StackF, PrintF)).
|
||||
1, Class, Reason, erlang:get_stacktrace(), StackF, PrintF)).
|
||||
|
||||
columns() ->
|
||||
case io:columns() of
|
||||
{ok, N} -> N;
|
||||
_-> 80
|
||||
{ok, N} -> N;
|
||||
_-> 80
|
||||
end.
|
||||
|
||||
lines(infinity, S) -> S;
|
||||
@ -804,8 +801,8 @@ recurse(Form, Else, F) ->
|
||||
do_transform(F, Acc, Forms, Context) ->
|
||||
Rec = fun do_transform/4, % this function
|
||||
F1 =
|
||||
fun(Form, Acc0) ->
|
||||
{Before1, Form1, After1, Recurse, Acc1} =
|
||||
fun(Form, Acc0) ->
|
||||
{Before1, Form1, After1, Recurse, Acc1} =
|
||||
this_form_rec(F, Form, Context, Acc0),
|
||||
if Recurse ->
|
||||
{NewForm, NewAcc} =
|
||||
@ -815,7 +812,7 @@ do_transform(F, Acc, Forms, Context) ->
|
||||
true ->
|
||||
{Before1, Form1, After1, Acc1}
|
||||
end
|
||||
end,
|
||||
end,
|
||||
mapfoldl(F1, Acc, Forms).
|
||||
|
||||
-spec do_depth_first(xform_f_df(), term(), forms(), #context{}) ->
|
||||
@ -825,7 +822,7 @@ do_depth_first(F, Acc, Forms, Context) ->
|
||||
F1 =
|
||||
fun(Form, Acc0) ->
|
||||
{NewForm, NewAcc} =
|
||||
enter_subtrees(Form, F, Context, Acc0, Rec),
|
||||
enter_subtrees(Form, F, Context, Acc0, Rec),
|
||||
this_form_df(F, NewForm, Context, NewAcc)
|
||||
end,
|
||||
mapfoldl(F1, Acc, Forms).
|
||||
@ -880,13 +877,13 @@ apply_F(F, Type, Form, Context, Acc) ->
|
||||
|
||||
update_context(Form, Context0) ->
|
||||
case type(Form) of
|
||||
function ->
|
||||
{Fun, Arity} =
|
||||
erl_syntax_lib:analyze_function(Form),
|
||||
Context0#context{function = Fun,
|
||||
arity = Arity};
|
||||
_ ->
|
||||
Context0
|
||||
function ->
|
||||
{Fun, Arity} =
|
||||
erl_syntax_lib:analyze_function(Form),
|
||||
Context0#context{function = Fun,
|
||||
arity = Arity};
|
||||
_ ->
|
||||
Context0
|
||||
end.
|
||||
|
||||
|
||||
@ -897,12 +894,12 @@ update_context(Form, Context0) ->
|
||||
%%% in question. The inserted forms are not transformed afterwards.
|
||||
mapfoldl(F, Accu0, [Hd|Tail]) ->
|
||||
{Before, Res, After, Accu1} =
|
||||
case F(Hd, Accu0) of
|
||||
{Be, _, Af, _} = Result when is_list(Be), is_list(Af) ->
|
||||
Result;
|
||||
{R1, A1} ->
|
||||
{[], R1, [], A1}
|
||||
end,
|
||||
case F(Hd, Accu0) of
|
||||
{Be, _, Af, _} = Result when is_list(Be), is_list(Af) ->
|
||||
Result;
|
||||
{R1, A1} ->
|
||||
{[], R1, [], A1}
|
||||
end,
|
||||
{Rs, Accu2} = mapfoldl(F, Accu1, Tail),
|
||||
{Before ++ [Res| After ++ Rs], Accu2};
|
||||
mapfoldl(F, Accu, []) when is_function(F, 2) -> {[], Accu}.
|
||||
@ -910,16 +907,16 @@ mapfoldl(F, Accu, []) when is_function(F, 2) -> {[], Accu}.
|
||||
|
||||
rpt_error(_Reason, _Fun, _Info, _Trace) ->
|
||||
%% Fmt = lists:flatten(
|
||||
%% ["*** ERROR in parse_transform function:~n"
|
||||
%% "*** Reason = ~p~n",
|
||||
%% ["*** ERROR in parse_transform function:~n"
|
||||
%% "*** Reason = ~p~n",
|
||||
%% "*** Location: ~p~n",
|
||||
%% "*** Trace: ~p~n",
|
||||
%% ["*** ~10w = ~p~n" || _ <- Info]]),
|
||||
%% "*** Trace: ~p~n",
|
||||
%% ["*** ~10w = ~p~n" || _ <- Info]]),
|
||||
%% Args = [Reason, Fun, Trace |
|
||||
%% lists:foldr(
|
||||
%% fun({K,V}, Acc) ->
|
||||
%% [K, V | Acc]
|
||||
%% end, [], Info)],
|
||||
%% lists:foldr(
|
||||
%% fun({K,V}, Acc) ->
|
||||
%% [K, V | Acc]
|
||||
%% end, [], Info)],
|
||||
%%io:format(Fmt, Args),
|
||||
ok.
|
||||
|
||||
@ -927,10 +924,10 @@ rpt_error(_Reason, _Fun, _Info, _Trace) ->
|
||||
iolist().
|
||||
format_error({E, [{M,F,A}|_]} = Error) ->
|
||||
try lists:flatten(io_lib:fwrite("~p in ~s:~s/~s", [E, atom_to_list(M),
|
||||
atom_to_list(F), integer_to_list(A)]))
|
||||
atom_to_list(F), integer_to_list(A)]))
|
||||
catch
|
||||
error:_ ->
|
||||
format_error_(Error)
|
||||
error:_ ->
|
||||
format_error_(Error)
|
||||
end;
|
||||
format_error(Error) ->
|
||||
format_error_(Error).
|
||||
|
@ -1,33 +1,29 @@
|
||||
%%% The contents of this file are subject to the Erlang Public License,
|
||||
%%% Version 1.1, (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.erlang.org/EPLICENSE
|
||||
%%%
|
||||
%%% Software distributed under the License is distributed on an "AS IS"
|
||||
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%%% the License for the specific language governing rights and limitations
|
||||
%%% under the License.
|
||||
%%%
|
||||
%%% The Original Code is exprecs-0.2.
|
||||
%%%
|
||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
||||
%%% All Rights Reserved.
|
||||
%%%
|
||||
%%% Contributor(s): ______________________________________.
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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.
|
||||
%% --------------------------------------------------
|
||||
%% File : parse_trans_codegen.erl
|
||||
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||
%% @end
|
||||
%%-------------------------------------------------------------------
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% File : parse_trans_codegen.erl
|
||||
%%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
||||
%%% @end
|
||||
%%% Description :
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
%%% @doc Parse transform for code generation pseduo functions
|
||||
%%%
|
||||
%%% <p>...</p>
|
||||
%%%
|
||||
%%% @end
|
||||
%% @doc Parse transform for code generation pseduo functions
|
||||
%%
|
||||
%% <p>...</p>
|
||||
%%
|
||||
%% @end
|
||||
|
||||
-module(parse_trans_codegen).
|
||||
|
||||
@ -150,100 +146,100 @@
|
||||
parse_transform(Forms, Options) ->
|
||||
Context = parse_trans:initial_context(Forms, Options),
|
||||
{NewForms, _} =
|
||||
parse_trans:do_depth_first(
|
||||
fun xform_fun/4, _Acc = Forms, Forms, Context),
|
||||
parse_trans:do_depth_first(
|
||||
fun xform_fun/4, _Acc = Forms, Forms, Context),
|
||||
parse_trans:return(parse_trans:revert(NewForms), Context).
|
||||
|
||||
xform_fun(application, Form, _Ctxt, Acc) ->
|
||||
MFA = erl_syntax_lib:analyze_application(Form),
|
||||
L = erl_syntax:get_pos(Form),
|
||||
case MFA of
|
||||
{codegen, {gen_module, 3}} ->
|
||||
[NameF, ExportsF, FunsF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForms = gen_module(NameF, ExportsF, FunsF, L, Acc),
|
||||
{NewForms, Acc};
|
||||
{codegen, {gen_function, 2}} ->
|
||||
[NameF, FunF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function(NameF, FunF, L, L, Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_function, 3}} ->
|
||||
[NameF, FunF, LineF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function(
|
||||
NameF, FunF, L, erl_syntax:integer_value(LineF), Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_function_alt, 3}} ->
|
||||
[NameF, FunF, AltF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function_alt(NameF, FunF, AltF, L, L, Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_functions, 1}} ->
|
||||
[List] = erl_syntax:application_arguments(Form),
|
||||
Elems = erl_syntax:list_elements(List),
|
||||
NewForms = lists:map(
|
||||
fun(E) ->
|
||||
[NameF, FunF] = erl_syntax:tuple_elements(E),
|
||||
gen_function(NameF, FunF, L, L, Acc)
|
||||
end, Elems),
|
||||
{erl_syntax:list(NewForms), Acc};
|
||||
{codegen, {exprs, 1}} ->
|
||||
[FunF] = erl_syntax:application_arguments(Form),
|
||||
[Clause] = erl_syntax:fun_expr_clauses(FunF),
|
||||
[{clause,_,_,_,Body}] = parse_trans:revert([Clause]),
|
||||
NewForm = substitute(erl_parse:abstract(Body)),
|
||||
{NewForm, Acc};
|
||||
_ ->
|
||||
{Form, Acc}
|
||||
{codegen, {gen_module, 3}} ->
|
||||
[NameF, ExportsF, FunsF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForms = gen_module(NameF, ExportsF, FunsF, L, Acc),
|
||||
{NewForms, Acc};
|
||||
{codegen, {gen_function, 2}} ->
|
||||
[NameF, FunF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function(NameF, FunF, L, L, Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_function, 3}} ->
|
||||
[NameF, FunF, LineF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function(
|
||||
NameF, FunF, L, erl_syntax:integer_value(LineF), Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_function_alt, 3}} ->
|
||||
[NameF, FunF, AltF] =
|
||||
erl_syntax:application_arguments(Form),
|
||||
NewForm = gen_function_alt(NameF, FunF, AltF, L, L, Acc),
|
||||
{NewForm, Acc};
|
||||
{codegen, {gen_functions, 1}} ->
|
||||
[List] = erl_syntax:application_arguments(Form),
|
||||
Elems = erl_syntax:list_elements(List),
|
||||
NewForms = lists:map(
|
||||
fun(E) ->
|
||||
[NameF, FunF] = erl_syntax:tuple_elements(E),
|
||||
gen_function(NameF, FunF, L, L, Acc)
|
||||
end, Elems),
|
||||
{erl_syntax:list(NewForms), Acc};
|
||||
{codegen, {exprs, 1}} ->
|
||||
[FunF] = erl_syntax:application_arguments(Form),
|
||||
[Clause] = erl_syntax:fun_expr_clauses(FunF),
|
||||
[{clause,_,_,_,Body}] = parse_trans:revert([Clause]),
|
||||
NewForm = substitute(erl_parse:abstract(Body)),
|
||||
{NewForm, Acc};
|
||||
_ ->
|
||||
{Form, Acc}
|
||||
end;
|
||||
xform_fun(_, Form, _Ctxt, Acc) ->
|
||||
{Form, Acc}.
|
||||
|
||||
gen_module(NameF, ExportsF, FunsF, L, Acc) ->
|
||||
case erl_syntax:type(FunsF) of
|
||||
list ->
|
||||
try gen_module_(NameF, ExportsF, FunsF, L, Acc)
|
||||
catch
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L, ?MODULE, ErrStr}}
|
||||
end;
|
||||
_ ->
|
||||
ErrStr = parse_trans:format_exception(
|
||||
error, "Argument must be a list"),
|
||||
{error, {L, ?MODULE, ErrStr}}
|
||||
list ->
|
||||
try gen_module_(NameF, ExportsF, FunsF, L, Acc)
|
||||
catch
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L, ?MODULE, ErrStr}}
|
||||
end;
|
||||
_ ->
|
||||
ErrStr = parse_trans:format_exception(
|
||||
error, "Argument must be a list"),
|
||||
{error, {L, ?MODULE, ErrStr}}
|
||||
end.
|
||||
|
||||
gen_module_(NameF, ExportsF, FunsF, L0, Acc) ->
|
||||
P = erl_syntax:get_pos(NameF),
|
||||
ModF = case parse_trans:revert_form(NameF) of
|
||||
{atom,_,_} = Am -> Am;
|
||||
{tuple,_,[{atom,_,'$var'},
|
||||
{var,_,V}]} ->
|
||||
{var,P,V}
|
||||
end,
|
||||
{atom,_,_} = Am -> Am;
|
||||
{tuple,_,[{atom,_,'$var'},
|
||||
{var,_,V}]} ->
|
||||
{var,P,V}
|
||||
end,
|
||||
cons(
|
||||
{cons,P,
|
||||
{tuple,P,
|
||||
[{atom,P,attribute},
|
||||
{integer,P,1},
|
||||
{atom,P,module},
|
||||
ModF]},
|
||||
[{atom,P,attribute},
|
||||
{integer,P,1},
|
||||
{atom,P,module},
|
||||
ModF]},
|
||||
substitute(
|
||||
abstract(
|
||||
[{attribute,P,export,
|
||||
lists:map(
|
||||
fun(TupleF) ->
|
||||
[F,A] = erl_syntax:tuple_elements(TupleF),
|
||||
{erl_syntax:atom_value(F), erl_syntax:integer_value(A)}
|
||||
end, erl_syntax:list_elements(ExportsF))}]))},
|
||||
abstract(
|
||||
[{attribute,P,export,
|
||||
lists:map(
|
||||
fun(TupleF) ->
|
||||
[F,A] = erl_syntax:tuple_elements(TupleF),
|
||||
{erl_syntax:atom_value(F), erl_syntax:integer_value(A)}
|
||||
end, erl_syntax:list_elements(ExportsF))}]))},
|
||||
lists:map(
|
||||
fun(FTupleF) ->
|
||||
Pos = erl_syntax:get_pos(FTupleF),
|
||||
[FName, FFunF] = erl_syntax:tuple_elements(FTupleF),
|
||||
gen_function(FName, FFunF, L0, Pos, Acc)
|
||||
end, erl_syntax:list_elements(FunsF))).
|
||||
fun(FTupleF) ->
|
||||
Pos = erl_syntax:get_pos(FTupleF),
|
||||
[FName, FFunF] = erl_syntax:tuple_elements(FTupleF),
|
||||
gen_function(FName, FFunF, L0, Pos, Acc)
|
||||
end, erl_syntax:list_elements(FunsF))).
|
||||
|
||||
cons({cons,L,H,T}, L2) ->
|
||||
{cons,L,H,cons(T, L2)};
|
||||
@ -258,80 +254,80 @@ cons({nil,L}, []) ->
|
||||
gen_function(NameF, FunF, L0, L, Acc) ->
|
||||
try gen_function_(NameF, FunF, [], L, Acc)
|
||||
catch
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L0, ?MODULE, ErrStr}}
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L0, ?MODULE, ErrStr}}
|
||||
end.
|
||||
|
||||
gen_function_alt(NameF, FunF, AltF, L0, L, Acc) ->
|
||||
try gen_function_(NameF, FunF, AltF, L, Acc)
|
||||
catch
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L0, ?MODULE, ErrStr}}
|
||||
error:E ->
|
||||
ErrStr = parse_trans:format_exception(error, E),
|
||||
{error, {L0, ?MODULE, ErrStr}}
|
||||
end.
|
||||
|
||||
gen_function_(NameF, FunF, AltF, L, Acc) ->
|
||||
case erl_syntax:type(FunF) of
|
||||
T when T==implicit_fun; T==fun_expr ->
|
||||
{Arity, Clauses} = gen_function_clauses(T, NameF, FunF, L, Acc),
|
||||
{tuple, 1, [{atom, 1, function},
|
||||
{integer, 1, L},
|
||||
NameF,
|
||||
{integer, 1, Arity},
|
||||
substitute(abstract(Clauses))]};
|
||||
list_comp ->
|
||||
%% Extract the fun from the LC
|
||||
[Template] = parse_trans:revert(
|
||||
[erl_syntax:list_comp_template(FunF)]),
|
||||
%% Process fun in the normal fashion (as above)
|
||||
{Arity, Clauses} = gen_function_clauses(erl_syntax:type(Template),
|
||||
NameF, Template, L, Acc),
|
||||
Body = erl_syntax:list_comp_body(FunF),
|
||||
%% Collect all variables from the LC generator(s)
|
||||
%% We want to produce an abstract representation of something like:
|
||||
%% {function,1,Name,Arity,
|
||||
%% lists:flatten(
|
||||
%% [(fun(V1,V2,...) ->
|
||||
%% ...
|
||||
%% end)(__V1,__V2,...) || {__V1,__V2,...} <- L])}
|
||||
%% where the __Vn vars are our renamed versions of the LC generator
|
||||
%% vars. This allows us to instantiate the clauses at run-time.
|
||||
Vars = lists:flatten(
|
||||
[sets:to_list(erl_syntax_lib:variables(
|
||||
erl_syntax:generator_pattern(G)))
|
||||
|| G <- Body]),
|
||||
Vars1 = [list_to_atom("__" ++ atom_to_list(V)) || V <- Vars],
|
||||
VarMap = lists:zip(Vars, Vars1),
|
||||
Body1 =
|
||||
[erl_syntax:generator(
|
||||
rename_vars(VarMap, gen_pattern(G)),
|
||||
gen_body(G)) || G <- Body],
|
||||
[RevLC] = parse_trans:revert(
|
||||
[erl_syntax:list_comp(
|
||||
{call, 1,
|
||||
{'fun',1,
|
||||
{clauses,
|
||||
[{clause,1,[{var,1,V} || V <- Vars],[],
|
||||
[substitute(
|
||||
abstract(Clauses))]
|
||||
}]}
|
||||
}, [{var,1,V} || V <- Vars1]}, Body1)]),
|
||||
AltC = case AltF of
|
||||
[] -> {nil,1};
|
||||
_ ->
|
||||
{Arity, AltC1} = gen_function_clauses(
|
||||
erl_syntax:type(AltF),
|
||||
NameF, AltF, L, Acc),
|
||||
substitute(abstract(AltC1))
|
||||
end,
|
||||
{tuple,1,[{atom,1,function},
|
||||
{integer, 1, L},
|
||||
NameF,
|
||||
{integer, 1, Arity},
|
||||
{call, 1, {remote, 1, {atom, 1, lists},
|
||||
{atom,1,flatten}},
|
||||
[{op, 1, '++', RevLC, AltC}]}]}
|
||||
T when T==implicit_fun; T==fun_expr ->
|
||||
{Arity, Clauses} = gen_function_clauses(T, NameF, FunF, L, Acc),
|
||||
{tuple, 1, [{atom, 1, function},
|
||||
{integer, 1, L},
|
||||
NameF,
|
||||
{integer, 1, Arity},
|
||||
substitute(abstract(Clauses))]};
|
||||
list_comp ->
|
||||
%% Extract the fun from the LC
|
||||
[Template] = parse_trans:revert(
|
||||
[erl_syntax:list_comp_template(FunF)]),
|
||||
%% Process fun in the normal fashion (as above)
|
||||
{Arity, Clauses} = gen_function_clauses(erl_syntax:type(Template),
|
||||
NameF, Template, L, Acc),
|
||||
Body = erl_syntax:list_comp_body(FunF),
|
||||
%% Collect all variables from the LC generator(s)
|
||||
%% We want to produce an abstract representation of something like:
|
||||
%% {function,1,Name,Arity,
|
||||
%% lists:flatten(
|
||||
%% [(fun(V1,V2,...) ->
|
||||
%% ...
|
||||
%% end)(__V1,__V2,...) || {__V1,__V2,...} <- L])}
|
||||
%% where the __Vn vars are our renamed versions of the LC generator
|
||||
%% vars. This allows us to instantiate the clauses at run-time.
|
||||
Vars = lists:flatten(
|
||||
[sets:to_list(erl_syntax_lib:variables(
|
||||
erl_syntax:generator_pattern(G)))
|
||||
|| G <- Body]),
|
||||
Vars1 = [list_to_atom("__" ++ atom_to_list(V)) || V <- Vars],
|
||||
VarMap = lists:zip(Vars, Vars1),
|
||||
Body1 =
|
||||
[erl_syntax:generator(
|
||||
rename_vars(VarMap, gen_pattern(G)),
|
||||
gen_body(G)) || G <- Body],
|
||||
[RevLC] = parse_trans:revert(
|
||||
[erl_syntax:list_comp(
|
||||
{call, 1,
|
||||
{'fun',1,
|
||||
{clauses,
|
||||
[{clause,1,[{var,1,V} || V <- Vars],[],
|
||||
[substitute(
|
||||
abstract(Clauses))]
|
||||
}]}
|
||||
}, [{var,1,V} || V <- Vars1]}, Body1)]),
|
||||
AltC = case AltF of
|
||||
[] -> {nil,1};
|
||||
_ ->
|
||||
{Arity, AltC1} = gen_function_clauses(
|
||||
erl_syntax:type(AltF),
|
||||
NameF, AltF, L, Acc),
|
||||
substitute(abstract(AltC1))
|
||||
end,
|
||||
{tuple,1,[{atom,1,function},
|
||||
{integer, 1, L},
|
||||
NameF,
|
||||
{integer, 1, Arity},
|
||||
{call, 1, {remote, 1, {atom, 1, lists},
|
||||
{atom,1,flatten}},
|
||||
[{op, 1, '++', RevLC, AltC}]}]}
|
||||
end.
|
||||
|
||||
gen_pattern(G) ->
|
||||
@ -343,21 +339,21 @@ gen_body(G) ->
|
||||
rename_vars(Vars, Tree) ->
|
||||
erl_syntax_lib:map(
|
||||
fun(T) ->
|
||||
case erl_syntax:type(T) of
|
||||
variable ->
|
||||
V = erl_syntax:variable_name(T),
|
||||
{_,V1} = lists:keyfind(V,1,Vars),
|
||||
erl_syntax:variable(V1);
|
||||
_ ->
|
||||
T
|
||||
end
|
||||
case erl_syntax:type(T) of
|
||||
variable ->
|
||||
V = erl_syntax:variable_name(T),
|
||||
{_,V1} = lists:keyfind(V,1,Vars),
|
||||
erl_syntax:variable(V1);
|
||||
_ ->
|
||||
T
|
||||
end
|
||||
end, Tree).
|
||||
|
||||
gen_function_clauses(implicit_fun, _NameF, FunF, _L, Acc) ->
|
||||
AQ = erl_syntax:implicit_fun_name(FunF),
|
||||
Name = erl_syntax:atom_value(erl_syntax:arity_qualifier_body(AQ)),
|
||||
Arity = erl_syntax:integer_value(
|
||||
erl_syntax:arity_qualifier_argument(AQ)),
|
||||
erl_syntax:arity_qualifier_argument(AQ)),
|
||||
NewForm = find_function(Name, Arity, Acc),
|
||||
ClauseForms = erl_syntax:function_clauses(NewForm),
|
||||
{Arity, ClauseForms};
|
||||
@ -368,32 +364,32 @@ gen_function_clauses(fun_expr, _NameF, FunF, _L, _Acc) ->
|
||||
|
||||
find_function(Name, Arity, Forms) ->
|
||||
[Form] = [F || {function,_,N,A,_} = F <- Forms,
|
||||
N == Name,
|
||||
A == Arity],
|
||||
N == Name,
|
||||
A == Arity],
|
||||
Form.
|
||||
|
||||
abstract(ClauseForms) ->
|
||||
erl_parse:abstract(parse_trans:revert(ClauseForms)).
|
||||
|
||||
substitute({tuple,L0,
|
||||
[{atom,_,tuple},
|
||||
{integer,_,L},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$var'}]},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,V}]},
|
||||
{nil,_}}}]}) ->
|
||||
[{atom,_,tuple},
|
||||
{integer,_,L},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$var'}]},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,V}]},
|
||||
{nil,_}}}]}) ->
|
||||
{call, L0, {remote,L0,{atom,L0,erl_parse},
|
||||
{atom,L0,abstract}},
|
||||
{atom,L0,abstract}},
|
||||
[{var, L0, V}, {integer, L0, L}]};
|
||||
substitute({tuple,L0,
|
||||
[{atom,_,tuple},
|
||||
{integer,_,_},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$form'}]},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,F}]},
|
||||
{nil,_}}}]}) ->
|
||||
[{atom,_,tuple},
|
||||
{integer,_,_},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$form'}]},
|
||||
{cons,_,
|
||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,F}]},
|
||||
{nil,_}}}]}) ->
|
||||
{var, L0, F};
|
||||
substitute([]) ->
|
||||
[];
|
||||
@ -407,17 +403,17 @@ substitute(X) ->
|
||||
get_arity(Clauses) ->
|
||||
Ays = [length(erl_syntax:clause_patterns(C)) || C <- Clauses],
|
||||
case lists:usort(Ays) of
|
||||
[Ay] ->
|
||||
Ay;
|
||||
Other ->
|
||||
erlang:error(ambiguous, Other)
|
||||
[Ay] ->
|
||||
Ay;
|
||||
Other ->
|
||||
erlang:error(ambiguous, Other)
|
||||
end.
|
||||
|
||||
|
||||
format_error(E) ->
|
||||
case io_lib:deep_char_list(E) of
|
||||
true ->
|
||||
E;
|
||||
_ ->
|
||||
io_lib:write(E)
|
||||
true ->
|
||||
E;
|
||||
_ ->
|
||||
io_lib:write(E)
|
||||
end.
|
||||
|
@ -41,14 +41,14 @@ transform_module(Mod, PT, Options) ->
|
||||
Forms = abstract_code(File),
|
||||
Context = parse_trans:initial_context(Forms, Options),
|
||||
PTMods = if is_atom(PT) -> [PT];
|
||||
is_function(PT, 2) -> [PT];
|
||||
is_list(PT) -> PT
|
||||
end,
|
||||
is_function(PT, 2) -> [PT];
|
||||
is_list(PT) -> PT
|
||||
end,
|
||||
Transformed = lists:foldl(fun(PTx, Fs) when is_function(PTx, 2) ->
|
||||
PTx(Fs, Options);
|
||||
(PTMod, Fs) ->
|
||||
PTMod:parse_transform(Fs, Options)
|
||||
end, Forms, PTMods),
|
||||
PTx(Fs, Options);
|
||||
(PTMod, Fs) ->
|
||||
PTMod:parse_transform(Fs, Options)
|
||||
end, Forms, PTMods),
|
||||
parse_trans:optionally_pretty_print(Transformed, Options, Context),
|
||||
compile_and_load_forms(Transformed, get_compile_options(Options)).
|
||||
|
||||
|
@ -1,45 +1,42 @@
|
||||
%%% The contents of this file are subject to the Erlang Public License,
|
||||
%%% Version 1.1, (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.erlang.org/EPLICENSE
|
||||
%%%
|
||||
%%% Software distributed under the License is distributed on an "AS IS"
|
||||
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%%% the License for the specific language governing rights and limitations
|
||||
%%% under the License.
|
||||
%%%
|
||||
%%% The Original Code is exprecs-0.2.
|
||||
%%%
|
||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
||||
%%% All Rights Reserved.
|
||||
%%%
|
||||
%%% Contributor(s): ______________________________________.
|
||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% --------------------------------------------------
|
||||
%% This file is provided to you 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.
|
||||
%% --------------------------------------------------
|
||||
%% File : parse_trans_pp.erl
|
||||
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||
%% @end
|
||||
%% Description :
|
||||
%%
|
||||
%% Created : 3 Aug 2010 by Ulf Wiger <ulf@wiger.net>
|
||||
%% --------------------------------------------------
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% File : parse_trans_pp.erl
|
||||
%%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
||||
%%% @end
|
||||
%%% Description :
|
||||
%%%
|
||||
%%% Created : 3 Aug 2010 by Ulf Wiger <ulf@feuerlabs.com>
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
%%% @doc Generic parse transform library for Erlang.
|
||||
%%%
|
||||
%%% This module contains some useful utility functions for inspecting
|
||||
%%% the results of parse transforms or code generation.
|
||||
%%% The function `main/1' is called from escript, and can be used to
|
||||
%%% pretty-print debug info in a .beam file from a Linux shell.
|
||||
%%%
|
||||
%%% Using e.g. the following bash alias:
|
||||
%%% <pre>
|
||||
%%% alias pp='escript $PARSE_TRANS_ROOT/ebin/parse_trans_pp.beam'
|
||||
%% @doc Generic parse transform library for Erlang.
|
||||
%%
|
||||
%% This module contains some useful utility functions for inspecting
|
||||
%% the results of parse transforms or code generation.
|
||||
%% The function `main/1' is called from escript, and can be used to
|
||||
%% pretty-print debug info in a .beam file from a Linux shell.
|
||||
%%
|
||||
%% Using e.g. the following bash alias:
|
||||
%% <pre>
|
||||
%% alias pp='escript $PARSE_TRANS_ROOT/ebin/parse_trans_pp.beam'
|
||||
%%% </pre>
|
||||
%%% a file could be pretty-printed using the following command:
|
||||
%%%
|
||||
%%% `$ pp ex_codegen.beam | less'
|
||||
%%% @end
|
||||
%% a file could be pretty-printed using the following command:
|
||||
%%
|
||||
%% `$ pp ex_codegen.beam | less'
|
||||
%% @end
|
||||
|
||||
-module(parse_trans_pp).
|
||||
|
||||
@ -103,13 +100,13 @@ pp_beam(F, Out) ->
|
||||
pp_beam_to_str(F) ->
|
||||
case beam_lib:chunks(F, [abstract_code]) of
|
||||
{ok, {_, [{abstract_code,{_,AC0}}]}} ->
|
||||
AC = epp:restore_typed_record_fields(AC0),
|
||||
AC = epp:restore_typed_record_fields(AC0),
|
||||
{ok, lists:flatten(
|
||||
%% io_lib:fwrite("~s~n", [erl_prettypr:format(
|
||||
%% erl_syntax:form_list(AC))])
|
||||
io_lib:fwrite("~s~n", [lists:flatten(
|
||||
[erl_pp:form(Form) ||
|
||||
Form <- AC])])
|
||||
io_lib:fwrite("~s~n", [lists:flatten(
|
||||
[erl_pp:form(Form) ||
|
||||
Form <- AC])])
|
||||
)};
|
||||
Other ->
|
||||
{error, Other}
|
||||
|
Loading…
Reference in New Issue
Block a user