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",
|
{erl_first_files, ["src/parse_trans.erl",
|
||||||
"src/parse_trans_pp.erl",
|
"src/parse_trans_pp.erl",
|
||||||
"src/parse_trans_codegen.erl"]}.
|
"src/parse_trans_codegen.erl"]}.
|
||||||
|
|
||||||
{erl_opts, [debug_info]}.
|
{erl_opts, [debug_info]}.
|
||||||
{xref_checks, [undefined_function_calls]}.
|
{xref_checks, [undefined_function_calls]}.
|
||||||
{deps, [{edown, ".*", {git, "git://github.com/uwiger/edown.git", {branch, "master"}}}]}.
|
|
||||||
{edoc_opts, [{doclet, edown_doclet},
|
{profiles,
|
||||||
{top_level_readme,
|
[{docs,
|
||||||
{"./README.md",
|
[
|
||||||
"http://github.com/uwiger/parse_trans"}}]}.
|
{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,
|
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||||
%%% 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
|
%% This file is provided to you under the Apache License,
|
||||||
%%% http://www.erlang.org/EPLICENSE
|
%% 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"
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
%%
|
||||||
%% the License for the specific language governing rights and limitations
|
%% 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.
|
%% 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
|
%% File : ct_expand.erl
|
||||||
%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||||
%% @end
|
%% @end
|
||||||
%% Description :
|
%% Created : 7 Apr 2010 by Ulf Wiger <ulf@wiger.net>
|
||||||
%%
|
|
||||||
%% Created : 7 Apr 2010 by Ulf Wiger <ulf@feuerlabs.com>
|
|
||||||
%%-------------------------------------------------------------------
|
%%-------------------------------------------------------------------
|
||||||
|
|
||||||
%% @doc Compile-time expansion utility
|
%% @doc Compile-time expansion utility
|
||||||
@ -53,7 +48,7 @@
|
|||||||
-export([parse_transform/2]).
|
-export([parse_transform/2]).
|
||||||
|
|
||||||
-export([extract_fun/3,
|
-export([extract_fun/3,
|
||||||
lfun_rewrite/2]).
|
lfun_rewrite/2]).
|
||||||
|
|
||||||
-type form() :: any().
|
-type form() :: any().
|
||||||
-type forms() :: [form()].
|
-type forms() :: [form()].
|
||||||
@ -65,37 +60,37 @@
|
|||||||
parse_transform(Forms, Options) ->
|
parse_transform(Forms, Options) ->
|
||||||
Trace = ct_trace_opt(Options, Forms),
|
Trace = ct_trace_opt(Options, Forms),
|
||||||
case parse_trans:depth_first(fun(T,F,C,A) ->
|
case parse_trans:depth_first(fun(T,F,C,A) ->
|
||||||
xform_fun(T,F,C,A,Forms, Trace)
|
xform_fun(T,F,C,A,Forms, Trace)
|
||||||
end, [], Forms, Options) of
|
end, [], Forms, Options) of
|
||||||
{error, Es} ->
|
{error, Es} ->
|
||||||
Es ++ Forms;
|
Es ++ Forms;
|
||||||
{NewForms, _} ->
|
{NewForms, _} ->
|
||||||
parse_trans:revert(NewForms)
|
parse_trans:revert(NewForms)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
ct_trace_opt(Options, Forms) ->
|
ct_trace_opt(Options, Forms) ->
|
||||||
case proplists:get_value(ct_expand_trace, Options) of
|
case proplists:get_value(ct_expand_trace, Options) of
|
||||||
undefined ->
|
undefined ->
|
||||||
case [Opt || {attribute,_,ct_expand_trace,Opt} <- Forms] of
|
case [Opt || {attribute,_,ct_expand_trace,Opt} <- Forms] of
|
||||||
[] ->
|
[] ->
|
||||||
[];
|
[];
|
||||||
[_|_] = L ->
|
[_|_] = L ->
|
||||||
lists:last(L)
|
lists:last(L)
|
||||||
end;
|
end;
|
||||||
Flags when is_list(Flags) ->
|
Flags when is_list(Flags) ->
|
||||||
Flags
|
Flags
|
||||||
end.
|
end.
|
||||||
|
|
||||||
xform_fun(application, Form, _Ctxt, Acc, Forms, Trace) ->
|
xform_fun(application, Form, _Ctxt, Acc, Forms, Trace) ->
|
||||||
MFA = erl_syntax_lib:analyze_application(Form),
|
MFA = erl_syntax_lib:analyze_application(Form),
|
||||||
case MFA of
|
case MFA of
|
||||||
{?MODULE, {term, 1}} ->
|
{?MODULE, {term, 1}} ->
|
||||||
LFH = fun(Name, Args, Bs) ->
|
LFH = fun(Name, Args, Bs) ->
|
||||||
eval_lfun(
|
eval_lfun(
|
||||||
extract_fun(Name, length(Args), Forms),
|
extract_fun(Name, length(Args), Forms),
|
||||||
Args, Bs, Forms, Trace)
|
Args, Bs, Forms, Trace)
|
||||||
end,
|
end,
|
||||||
Args = erl_syntax:application_arguments(Form),
|
Args = erl_syntax:application_arguments(Form),
|
||||||
RevArgs = parse_trans:revert(Args),
|
RevArgs = parse_trans:revert(Args),
|
||||||
case erl_eval:exprs(RevArgs, [], {eval, LFH}) of
|
case erl_eval:exprs(RevArgs, [], {eval, LFH}) of
|
||||||
{value, Value,[]} ->
|
{value, Value,[]} ->
|
||||||
@ -113,43 +108,43 @@ xform_fun(_, Form, _Ctxt, Acc, _, _) ->
|
|||||||
|
|
||||||
extract_fun(Name, Arity, Forms) ->
|
extract_fun(Name, Arity, Forms) ->
|
||||||
case [F_ || {function,_,N_,A_,_Cs} = F_ <- Forms,
|
case [F_ || {function,_,N_,A_,_Cs} = F_ <- Forms,
|
||||||
N_ == Name, A_ == Arity] of
|
N_ == Name, A_ == Arity] of
|
||||||
[] ->
|
[] ->
|
||||||
erlang:error({undef, [{Name, Arity}]});
|
erlang:error({undef, [{Name, Arity}]});
|
||||||
[FForm] ->
|
[FForm] ->
|
||||||
FForm
|
FForm
|
||||||
end.
|
end.
|
||||||
|
|
||||||
eval_lfun({function,L,F,_,Clauses}, Args, Bs, Forms, Trace) ->
|
eval_lfun({function,L,F,_,Clauses}, Args, Bs, Forms, Trace) ->
|
||||||
try
|
try
|
||||||
begin
|
begin
|
||||||
{ArgsV, Bs1} = lists:mapfoldl(
|
{ArgsV, Bs1} = lists:mapfoldl(
|
||||||
fun(A, Bs_) ->
|
fun(A, Bs_) ->
|
||||||
{value,AV,Bs1_} =
|
{value,AV,Bs1_} =
|
||||||
erl_eval:expr(A, Bs_, lfh(Forms, Trace)),
|
erl_eval:expr(A, Bs_, lfh(Forms, Trace)),
|
||||||
{abstract(AV), Bs1_}
|
{abstract(AV), Bs1_}
|
||||||
end, Bs, Args),
|
end, Bs, Args),
|
||||||
Expr = {call, L, {'fun', L, {clauses, lfun_rewrite(Clauses, Forms)}}, ArgsV},
|
Expr = {call, L, {'fun', L, {clauses, lfun_rewrite(Clauses, Forms)}}, ArgsV},
|
||||||
call_trace(Trace =/= [], L, F, ArgsV),
|
call_trace(Trace =/= [], L, F, ArgsV),
|
||||||
{value, Ret, _} =
|
{value, Ret, _} =
|
||||||
erl_eval:expr(Expr, erl_eval:new_bindings(), lfh(Forms, Trace)),
|
erl_eval:expr(Expr, erl_eval:new_bindings(), lfh(Forms, Trace)),
|
||||||
ret_trace(lists:member(r, Trace) orelse lists:member(x, Trace),
|
ret_trace(lists:member(r, Trace) orelse lists:member(x, Trace),
|
||||||
L, F, Args, Ret),
|
L, F, Args, Ret),
|
||||||
%% restore bindings
|
%% restore bindings
|
||||||
{value, Ret, Bs1}
|
{value, Ret, Bs1}
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
error:Err ->
|
error:Err ->
|
||||||
exception_trace(lists:member(x, Trace), L, F, Args, Err),
|
exception_trace(lists:member(x, Trace), L, F, Args, Err),
|
||||||
error(Err)
|
error(Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
lfh(Forms, Trace) ->
|
lfh(Forms, Trace) ->
|
||||||
{eval, fun(Name, As, Bs1) ->
|
{eval, fun(Name, As, Bs1) ->
|
||||||
eval_lfun(
|
eval_lfun(
|
||||||
extract_fun(Name, length(As), Forms),
|
extract_fun(Name, length(As), Forms),
|
||||||
As, Bs1, Forms, Trace)
|
As, Bs1, Forms, Trace)
|
||||||
end}.
|
end}.
|
||||||
|
|
||||||
call_trace(false, _, _, _) -> ok;
|
call_trace(false, _, _, _) -> ok;
|
||||||
call_trace(true, L, F, As) ->
|
call_trace(true, L, F, As) ->
|
||||||
@ -159,14 +154,14 @@ pp_function(F, []) ->
|
|||||||
atom_to_list(F) ++ "()";
|
atom_to_list(F) ++ "()";
|
||||||
pp_function(F, [A|As]) ->
|
pp_function(F, [A|As]) ->
|
||||||
lists:flatten([atom_to_list(F), "(",
|
lists:flatten([atom_to_list(F), "(",
|
||||||
[io_lib:fwrite("~w", [erl_parse:normalise(A)]) |
|
[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_)])] || A_ <- As]],
|
||||||
")"]).
|
")"]).
|
||||||
|
|
||||||
ret_trace(false, _, _, _, _) -> ok;
|
ret_trace(false, _, _, _, _) -> ok;
|
||||||
ret_trace(true, L, F, Args, Res) ->
|
ret_trace(true, L, F, Args, Res) ->
|
||||||
io:fwrite("ct_expand (~w): returned from ~w/~w: ~w~n",
|
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(false, _, _, _, _) -> ok;
|
||||||
exception_trace(true, L, F, Args, Err) ->
|
exception_trace(true, L, F, Args, Err) ->
|
||||||
@ -176,10 +171,10 @@ exception_trace(true, L, F, Args, Err) ->
|
|||||||
lfun_rewrite(Exprs, Forms) ->
|
lfun_rewrite(Exprs, Forms) ->
|
||||||
parse_trans:plain_transform(
|
parse_trans:plain_transform(
|
||||||
fun({'fun',L,{function,F,A}}) ->
|
fun({'fun',L,{function,F,A}}) ->
|
||||||
{function,_,_,_,Cs} = extract_fun(F, A, Forms),
|
{function,_,_,_,Cs} = extract_fun(F, A, Forms),
|
||||||
{'fun',L,{clauses, Cs}};
|
{'fun',L,{clauses, Cs}};
|
||||||
(_) ->
|
(_) ->
|
||||||
continue
|
continue
|
||||||
end, Exprs).
|
end, Exprs).
|
||||||
|
|
||||||
|
|
||||||
@ -190,15 +185,15 @@ lfun_rewrite(Exprs, Forms) ->
|
|||||||
AbsTerm :: abstract_expr().
|
AbsTerm :: abstract_expr().
|
||||||
abstract(T) when is_function(T) ->
|
abstract(T) when is_function(T) ->
|
||||||
case erlang:fun_info(T, module) of
|
case erlang:fun_info(T, module) of
|
||||||
{module, erl_eval} ->
|
{module, erl_eval} ->
|
||||||
case erl_eval:fun_data(T) of
|
case erl_eval:fun_data(T) of
|
||||||
{fun_data, _Imports, Clauses} ->
|
{fun_data, _Imports, Clauses} ->
|
||||||
{'fun', 0, {clauses, Clauses}};
|
{'fun', 0, {clauses, Clauses}};
|
||||||
false ->
|
false ->
|
||||||
erlang:error(function_clause) % mimicking erl_parse:abstract(T)
|
erlang:error(function_clause) % mimicking erl_parse:abstract(T)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
erlang:error(function_clause)
|
erlang:error(function_clause)
|
||||||
end;
|
end;
|
||||||
abstract(T) when is_integer(T) -> {integer,0,T};
|
abstract(T) when is_integer(T) -> {integer,0,T};
|
||||||
abstract(T) when is_float(T) -> {float,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 -*-
|
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||||
%%% 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
|
%% This file is provided to you under the Apache License,
|
||||||
%%% compliance with the License. You may obtain a copy of the License at
|
%% Version 2.0 (the "License"); you may not use this file
|
||||||
%%% http://www.erlang.org/EPLICENSE
|
%% 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
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||||
%%% the License for the specific language governing rights and limitations
|
%%
|
||||||
%%% under the License.
|
%% Unless required by applicable law or agreed to in writing,
|
||||||
%%%
|
%% software distributed under the License is distributed on an
|
||||||
%%% The Original Code is exprecs-0.2.
|
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
%%%
|
%% KIND, either express or implied. See the License for the
|
||||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
%% specific language governing permissions and limitations
|
||||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
%% under the License.
|
||||||
%%% All Rights Reserved.
|
%% --------------------------------------------------
|
||||||
%%%
|
%%
|
||||||
%%% Contributor(s): ______________________________________.
|
%% @author Ulf Wiger <ulf@wiger.net>
|
||||||
|
%% @doc Parse transform library.
|
||||||
%%% @author Ulf Wiger <ulf.wiger@feuerlabs.com>
|
%% @end
|
||||||
%%% @doc This is a container for parse_trans modules.
|
|
||||||
%%% @end
|
|
||||||
{application, parse_trans,
|
{application, parse_trans,
|
||||||
[{description, "Parse transform library"},
|
[{description, "Parse transform library"},
|
||||||
{vsn, git},
|
{vsn, git},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications, [kernel, stdlib, syntax_tools]},
|
{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,
|
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||||
%%% 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
|
%% This file is provided to you under the Apache License,
|
||||||
%%% http://www.erlang.org/EPLICENSE
|
%% Version 2.0 (the "License"); you may not use this file
|
||||||
%%%
|
%% except in compliance with the License. You may obtain
|
||||||
%%% Software distributed under the License is distributed on an "AS IS"
|
%% a copy of the License at
|
||||||
%%% 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
|
||||||
%%% under the License.
|
%%
|
||||||
%%%
|
%% Unless required by applicable law or agreed to in writing,
|
||||||
%%% The Original Code is exprecs-0.2.
|
%% software distributed under the License is distributed on an
|
||||||
%%%
|
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
%% KIND, either express or implied. See the License for the
|
||||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
%% specific language governing permissions and limitations
|
||||||
%%% All Rights Reserved.
|
%% under the License.
|
||||||
%%%
|
%% --------------------------------------------------
|
||||||
%%% Contributor(s): ______________________________________.
|
%% File : parse_trans.erl
|
||||||
|
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||||
%%%-------------------------------------------------------------------
|
%% @end
|
||||||
%%% File : parse_trans.erl
|
%% Description :
|
||||||
%%% @author : Ulf Wiger <ulf.wiger@feuerlabs.com>
|
%%
|
||||||
%%% @end
|
%% Created : 13 Feb 2006 by Ulf Wiger <ulf@wiger.net> (then Ericsson)
|
||||||
%%% Description :
|
|
||||||
%%%
|
|
||||||
%%% Created : 13 Feb 2006 by Ulf Wiger <ulf.wiger@feuerlabs.com> (then Ericsson)
|
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
%%% @doc Generic parse transform library for Erlang.
|
%% @doc Generic parse transform library for Erlang.
|
||||||
%%%
|
%%
|
||||||
%%% <p>...</p>
|
%% <p>...</p>
|
||||||
%%%
|
%%
|
||||||
%%% @end
|
%% @end
|
||||||
|
|
||||||
-module(parse_trans).
|
-module(parse_trans).
|
||||||
|
|
||||||
@ -37,12 +34,12 @@
|
|||||||
|
|
||||||
-export([
|
-export([
|
||||||
inspect/4,
|
inspect/4,
|
||||||
transform/4,
|
transform/4,
|
||||||
depth_first/4,
|
depth_first/4,
|
||||||
revert/1,
|
revert/1,
|
||||||
revert_form/1,
|
revert_form/1,
|
||||||
format_exception/2, format_exception/3,
|
format_exception/2, format_exception/3,
|
||||||
return/2
|
return/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
@ -55,13 +52,13 @@
|
|||||||
do_inspect/4,
|
do_inspect/4,
|
||||||
do_transform/4,
|
do_transform/4,
|
||||||
do_depth_first/4,
|
do_depth_first/4,
|
||||||
top/3
|
top/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([do_insert_forms/4,
|
-export([do_insert_forms/4,
|
||||||
replace_function/4,
|
replace_function/4,
|
||||||
replace_function/5,
|
replace_function/5,
|
||||||
export_function/3]).
|
export_function/3]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
context/2,
|
context/2,
|
||||||
@ -85,8 +82,8 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
-record(context, {module,
|
-record(context, {module,
|
||||||
function,
|
function,
|
||||||
arity,
|
arity,
|
||||||
file,
|
file,
|
||||||
options}).
|
options}).
|
||||||
|
|
||||||
@ -97,7 +94,7 @@
|
|||||||
|
|
||||||
-define(ERROR(R, F, I),
|
-define(ERROR(R, F, I),
|
||||||
begin
|
begin
|
||||||
Trace = erlang:get_stacktrace(),
|
Trace = erlang:get_stacktrace(),
|
||||||
rpt_error(R, F, I, Trace),
|
rpt_error(R, F, I, Trace),
|
||||||
throw({error,get_pos(I),{R, Trace}})
|
throw({error,get_pos(I),{R, Trace}})
|
||||||
end).
|
end).
|
||||||
@ -110,11 +107,11 @@
|
|||||||
-type options() :: [{atom(), any()}].
|
-type options() :: [{atom(), any()}].
|
||||||
-type type() :: atom().
|
-type type() :: atom().
|
||||||
-type xform_f_rec() :: fun((type(), form(), #context{}, Acc) ->
|
-type xform_f_rec() :: fun((type(), form(), #context{}, Acc) ->
|
||||||
{form(), boolean(), Acc}
|
{form(), boolean(), Acc}
|
||||||
| {forms(), form(), forms(), boolean(), Acc}).
|
| {forms(), form(), forms(), boolean(), Acc}).
|
||||||
-type xform_f_df() :: fun((type(), form(), #context{}, Acc) ->
|
-type xform_f_df() :: fun((type(), form(), #context{}, Acc) ->
|
||||||
{form(), Acc}
|
{form(), Acc}
|
||||||
| {forms(), form(), forms(), Acc}).
|
| {forms(), form(), forms(), Acc}).
|
||||||
-type insp_f() :: fun((type(), form(), #context{}, A) -> {boolean(), A}).
|
-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)) ->
|
plain_transform1(Fun, [F|Fs]) when is_atom(element(1,F)) ->
|
||||||
case Fun(F) of
|
case Fun(F) of
|
||||||
skip ->
|
skip ->
|
||||||
plain_transform1(Fun, Fs);
|
plain_transform1(Fun, Fs);
|
||||||
continue ->
|
continue ->
|
||||||
[list_to_tuple(plain_transform1(Fun, tuple_to_list(F))) |
|
[list_to_tuple(plain_transform1(Fun, tuple_to_list(F))) |
|
||||||
plain_transform1(Fun, Fs)];
|
plain_transform1(Fun, Fs)];
|
||||||
{done, NewF} ->
|
{done, NewF} ->
|
||||||
[NewF | Fs];
|
[NewF | Fs];
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
error(Reason, F, [{form, F}]);
|
error(Reason, F, [{form, F}]);
|
||||||
NewF when is_tuple(NewF) ->
|
NewF when is_tuple(NewF) ->
|
||||||
[NewF | plain_transform1(Fun, Fs)]
|
[NewF | plain_transform1(Fun, Fs)]
|
||||||
end;
|
end;
|
||||||
plain_transform1(Fun, [L|Fs]) when is_list(L) ->
|
plain_transform1(Fun, [L|Fs]) when is_list(L) ->
|
||||||
[plain_transform1(Fun, L) | plain_transform1(Fun, Fs)];
|
[plain_transform1(Fun, L) | plain_transform1(Fun, Fs)];
|
||||||
@ -204,10 +201,10 @@ plain_transform1(_, F) ->
|
|||||||
integer().
|
integer().
|
||||||
get_pos(I) when is_list(I) ->
|
get_pos(I) when is_list(I) ->
|
||||||
case proplists:get_value(form, I) of
|
case proplists:get_value(form, I) of
|
||||||
undefined ->
|
undefined ->
|
||||||
?DUMMY_LINE;
|
?DUMMY_LINE;
|
||||||
Form ->
|
Form ->
|
||||||
erl_syntax:get_pos(Form)
|
erl_syntax:get_pos(Form)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -243,7 +240,7 @@ get_module(Forms) ->
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%%
|
%%%
|
||||||
-spec get_attribute(atom(), [any()]) ->
|
-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) -> get_attribute(A,Forms,[erl_syntax:atom(undefined)]).
|
||||||
get_attribute(A, Forms, Undef) ->
|
get_attribute(A, Forms, Undef) ->
|
||||||
@ -318,17 +315,17 @@ do(Transform, Fun, Acc, Forms, Options) ->
|
|||||||
Context = initial_context(Forms, Options),
|
Context = initial_context(Forms, Options),
|
||||||
File = Context#context.file,
|
File = Context#context.file,
|
||||||
try Transform(Fun, Acc, Forms, Context) of
|
try Transform(Fun, Acc, Forms, Context) of
|
||||||
{NewForms, Acc1} when is_list(NewForms) ->
|
{NewForms, Acc1} when is_list(NewForms) ->
|
||||||
NewForms1 = optionally_renumber(NewForms, Options),
|
NewForms1 = optionally_renumber(NewForms, Options),
|
||||||
optionally_pretty_print(NewForms1, Options, Context),
|
optionally_pretty_print(NewForms1, Options, Context),
|
||||||
{NewForms1, Acc1}
|
{NewForms1, Acc1}
|
||||||
catch
|
catch
|
||||||
error:Reason ->
|
error:Reason ->
|
||||||
{error,
|
{error,
|
||||||
[{File, [{?DUMMY_LINE, ?MODULE,
|
[{File, [{?DUMMY_LINE, ?MODULE,
|
||||||
{Reason, erlang:get_stacktrace()}}]}]};
|
{Reason, erlang:get_stacktrace()}}]}]};
|
||||||
throw:{error, Ln, What} ->
|
throw:{error, Ln, What} ->
|
||||||
{error, [{error, {Ln, ?MODULE, What}}]}
|
{error, [{error, {Ln, ?MODULE, What}}]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec top(function(), forms(), list()) ->
|
-spec top(function(), forms(), list()) ->
|
||||||
@ -337,18 +334,18 @@ top(F, Forms, Options) ->
|
|||||||
Context = initial_context(Forms, Options),
|
Context = initial_context(Forms, Options),
|
||||||
File = Context#context.file,
|
File = Context#context.file,
|
||||||
try F(Forms, Context) of
|
try F(Forms, Context) of
|
||||||
{error, Reason} -> {error, Reason};
|
{error, Reason} -> {error, Reason};
|
||||||
NewForms when is_list(NewForms) ->
|
NewForms when is_list(NewForms) ->
|
||||||
NewForms1 = optionally_renumber(NewForms, Options),
|
NewForms1 = optionally_renumber(NewForms, Options),
|
||||||
optionally_pretty_print(NewForms1, Options, Context),
|
optionally_pretty_print(NewForms1, Options, Context),
|
||||||
NewForms1
|
NewForms1
|
||||||
catch
|
catch
|
||||||
error:Reason ->
|
error:Reason ->
|
||||||
{error,
|
{error,
|
||||||
[{File, [{?DUMMY_LINE, ?MODULE,
|
[{File, [{?DUMMY_LINE, ?MODULE,
|
||||||
{Reason, erlang:get_stacktrace()}}]}]};
|
{Reason, erlang:get_stacktrace()}}]}]};
|
||||||
throw:{error, Ln, What} ->
|
throw:{error, Ln, What} ->
|
||||||
{error, [{File, [{Ln, ?MODULE, What}]}], []}
|
{error, [{File, [{Ln, ?MODULE, What}]}], []}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
replace_function(F, Arity, NewForm, Forms) ->
|
replace_function(F, Arity, NewForm, Forms) ->
|
||||||
@ -356,39 +353,39 @@ replace_function(F, Arity, NewForm, Forms) ->
|
|||||||
|
|
||||||
replace_function(F, Arity, NewForm, Forms, Opts) ->
|
replace_function(F, Arity, NewForm, Forms, Opts) ->
|
||||||
{NewForms, _} =
|
{NewForms, _} =
|
||||||
do_transform(
|
do_transform(
|
||||||
fun(function, Form, _Ctxt, Acc) ->
|
fun(function, Form, _Ctxt, Acc) ->
|
||||||
case erl_syntax:revert(Form) of
|
case erl_syntax:revert(Form) of
|
||||||
{function, _, F, Arity, _} = RevForm ->
|
{function, _, F, Arity, _} = RevForm ->
|
||||||
{[], NewForm, with_original_f(RevForm, Opts),
|
{[], NewForm, with_original_f(RevForm, Opts),
|
||||||
false, Acc};
|
false, Acc};
|
||||||
_ ->
|
_ ->
|
||||||
{Form, false, Acc}
|
{Form, false, Acc}
|
||||||
end;
|
end;
|
||||||
(_, Form, _Ctxt, Acc) ->
|
(_, Form, _Ctxt, Acc) ->
|
||||||
{Form, false, Acc}
|
{Form, false, Acc}
|
||||||
end, false, Forms, initial_context(Forms, [])),
|
end, false, Forms, initial_context(Forms, [])),
|
||||||
revert(maybe_export_renamed(NewForms, Arity, Opts)).
|
revert(maybe_export_renamed(NewForms, Arity, Opts)).
|
||||||
|
|
||||||
with_original_f({function,_,_,_,_} = Form, Opts) ->
|
with_original_f({function,_,_,_,_} = Form, Opts) ->
|
||||||
case lists:keyfind(rename_original, 1, Opts) of
|
case lists:keyfind(rename_original, 1, Opts) of
|
||||||
{_, NewName} when is_atom(NewName) ->
|
{_, NewName} when is_atom(NewName) ->
|
||||||
[setelement(3, Form, NewName)];
|
[setelement(3, Form, NewName)];
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
maybe_export_renamed(Forms, Arity, Opts) ->
|
maybe_export_renamed(Forms, Arity, Opts) ->
|
||||||
case lists:keyfind(rename_original, 1, Opts) of
|
case lists:keyfind(rename_original, 1, Opts) of
|
||||||
{_, NewName} when is_atom(NewName) ->
|
{_, NewName} when is_atom(NewName) ->
|
||||||
export_function(NewName, Arity, Forms);
|
export_function(NewName, Arity, Forms);
|
||||||
_ ->
|
_ ->
|
||||||
Forms
|
Forms
|
||||||
end.
|
end.
|
||||||
|
|
||||||
export_function(F, Arity, Forms) ->
|
export_function(F, Arity, Forms) ->
|
||||||
do_insert_forms(above, [{attribute, 1, export, [{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{}) ->
|
-spec do_insert_forms(above | below, forms(), forms(), #context{}) ->
|
||||||
forms().
|
forms().
|
||||||
@ -420,12 +417,12 @@ optionally_pretty_print(Result, Options, Context) ->
|
|||||||
DoLFs = option_value(pt_log_forms, Options, Result),
|
DoLFs = option_value(pt_log_forms, Options, Result),
|
||||||
File = Context#context.file,
|
File = Context#context.file,
|
||||||
if DoLFs ->
|
if DoLFs ->
|
||||||
Out1 = outfile(File, forms),
|
Out1 = outfile(File, forms),
|
||||||
{ok,Fd} = file:open(Out1, [write]),
|
{ok,Fd} = file:open(Out1, [write]),
|
||||||
try lists:foreach(fun(F) -> io:fwrite(Fd, "~p.~n", [F]) end, Result)
|
try lists:foreach(fun(F) -> io:fwrite(Fd, "~p.~n", [F]) end, Result)
|
||||||
after
|
after
|
||||||
ok = file:close(Fd)
|
ok = file:close(Fd)
|
||||||
end;
|
end;
|
||||||
true -> ok
|
true -> ok
|
||||||
end,
|
end,
|
||||||
if DoPP ->
|
if DoPP ->
|
||||||
@ -437,12 +434,12 @@ optionally_pretty_print(Result, Options, Context) ->
|
|||||||
|
|
||||||
optionally_renumber(Result, Options) ->
|
optionally_renumber(Result, Options) ->
|
||||||
case option_value(pt_renumber, Options, Result) of
|
case option_value(pt_renumber, Options, Result) of
|
||||||
true ->
|
true ->
|
||||||
io:fwrite("renumbering...~n", []),
|
io:fwrite("renumbering...~n", []),
|
||||||
Rev = revert(Result),
|
Rev = revert(Result),
|
||||||
renumber_(Rev);
|
renumber_(Rev);
|
||||||
false ->
|
false ->
|
||||||
Result
|
Result
|
||||||
end.
|
end.
|
||||||
|
|
||||||
renumber_(L) when is_list(L) ->
|
renumber_(L) when is_list(L) ->
|
||||||
@ -453,15 +450,15 @@ renumber_(L, Acc) when is_list(L) ->
|
|||||||
lists:mapfoldl(fun renumber_/2, Acc, L);
|
lists:mapfoldl(fun renumber_/2, Acc, L);
|
||||||
renumber_(T, Prev) when is_tuple(T) ->
|
renumber_(T, Prev) when is_tuple(T) ->
|
||||||
case is_form(T) of
|
case is_form(T) of
|
||||||
true ->
|
true ->
|
||||||
New = Prev+1,
|
New = Prev+1,
|
||||||
T1 = setelement(2, T, New),
|
T1 = setelement(2, T, New),
|
||||||
{Res, NewAcc} = renumber_(tuple_to_list(T1), New),
|
{Res, NewAcc} = renumber_(tuple_to_list(T1), New),
|
||||||
{list_to_tuple(Res), NewAcc};
|
{list_to_tuple(Res), NewAcc};
|
||||||
false ->
|
false ->
|
||||||
L = tuple_to_list(T),
|
L = tuple_to_list(T),
|
||||||
{Res, NewAcc} = renumber_(L, Prev),
|
{Res, NewAcc} = renumber_(L, Prev),
|
||||||
{list_to_tuple(Res), NewAcc}
|
{list_to_tuple(Res), NewAcc}
|
||||||
end;
|
end;
|
||||||
renumber_(X, Prev) ->
|
renumber_(X, Prev) ->
|
||||||
{X, Prev}.
|
{X, Prev}.
|
||||||
@ -469,10 +466,10 @@ renumber_(X, Prev) ->
|
|||||||
is_form(T) when element(1,T)==type -> true;
|
is_form(T) when element(1,T)==type -> true;
|
||||||
is_form(T) ->
|
is_form(T) ->
|
||||||
try erl_syntax:type(T),
|
try erl_syntax:type(T),
|
||||||
true
|
true
|
||||||
catch
|
catch
|
||||||
error:_ ->
|
error:_ ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
option_value(Key, Options, Result) ->
|
option_value(Key, Options, Result) ->
|
||||||
@ -606,12 +603,12 @@ revert_form(F) ->
|
|||||||
|
|
||||||
revert_form(F, W) ->
|
revert_form(F, W) ->
|
||||||
case erl_syntax:revert(F) of
|
case erl_syntax:revert(F) of
|
||||||
{attribute,L,A,Tree} when element(1,Tree) == tree ->
|
{attribute,L,A,Tree} when element(1,Tree) == tree ->
|
||||||
{attribute,L,A,erl_syntax:revert(Tree)};
|
{attribute,L,A,erl_syntax:revert(Tree)};
|
||||||
Result ->
|
Result ->
|
||||||
if W -> fix_impl_fun(Result);
|
if W -> fix_impl_fun(Result);
|
||||||
true -> Result
|
true -> Result
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
fix_impl_fun({'fun',L,{function,{atom,_,Fn},{integer,_,Ay}}}) ->
|
fix_impl_fun({'fun',L,{function,{atom,_,Fn},{integer,_,Ay}}}) ->
|
||||||
@ -627,26 +624,26 @@ fix_impl_fun(X) ->
|
|||||||
|
|
||||||
needs_revert_workaround() ->
|
needs_revert_workaround() ->
|
||||||
case application:get_env(parse_trans,revert_workaround) of
|
case application:get_env(parse_trans,revert_workaround) of
|
||||||
{ok, Bool} when is_boolean(Bool) -> Bool;
|
{ok, Bool} when is_boolean(Bool) -> Bool;
|
||||||
_ ->
|
_ ->
|
||||||
Res = try lint_reverted()
|
Res = try lint_reverted()
|
||||||
catch
|
catch
|
||||||
error:_ ->
|
error:_ ->
|
||||||
true
|
true
|
||||||
end,
|
end,
|
||||||
application:set_env(parse_trans,revert_workaround,Res),
|
application:set_env(parse_trans,revert_workaround,Res),
|
||||||
Res
|
Res
|
||||||
end.
|
end.
|
||||||
|
|
||||||
lint_reverted() ->
|
lint_reverted() ->
|
||||||
Ts = [{attribute,1,module,m},
|
Ts = [{attribute,1,module,m},
|
||||||
{attribute,2,export,[{f,0}]},
|
{attribute,2,export,[{f,0}]},
|
||||||
erl_syntax:function(erl_syntax:atom(f),
|
erl_syntax:function(erl_syntax:atom(f),
|
||||||
[erl_syntax:clause(
|
[erl_syntax:clause(
|
||||||
[],
|
[],
|
||||||
[erl_syntax:implicit_fun(
|
[erl_syntax:implicit_fun(
|
||||||
erl_syntax:atom(f),
|
erl_syntax:atom(f),
|
||||||
erl_syntax:integer(0))])])],
|
erl_syntax:integer(0))])])],
|
||||||
Rev = erl_syntax:revert_forms(Ts),
|
Rev = erl_syntax:revert_forms(Ts),
|
||||||
erl_lint:module(Rev),
|
erl_lint:module(Rev),
|
||||||
false.
|
false.
|
||||||
@ -675,23 +672,23 @@ lint_reverted() ->
|
|||||||
%%% @end
|
%%% @end
|
||||||
return(Forms, Context) ->
|
return(Forms, Context) ->
|
||||||
JustForms = plain_transform(
|
JustForms = plain_transform(
|
||||||
fun({error,_}) -> skip;
|
fun({error,_}) -> skip;
|
||||||
({warning,_}) -> skip;
|
({warning,_}) -> skip;
|
||||||
(_) -> continue
|
(_) -> continue
|
||||||
end, Forms),
|
end, Forms),
|
||||||
File = case Context of
|
File = case Context of
|
||||||
#context{file = F} -> F;
|
#context{file = F} -> F;
|
||||||
_ -> "parse_transform"
|
_ -> "parse_transform"
|
||||||
end,
|
end,
|
||||||
case {find_forms(Forms, error), find_forms(Forms, warning)} of
|
case {find_forms(Forms, error), find_forms(Forms, warning)} of
|
||||||
{[], []} ->
|
{[], []} ->
|
||||||
JustForms;
|
JustForms;
|
||||||
{[], Ws} ->
|
{[], Ws} ->
|
||||||
{warnings, JustForms, [{File, [W || {warning,W} <- Ws]}]};
|
{warnings, JustForms, [{File, [W || {warning,W} <- Ws]}]};
|
||||||
{Es, Ws} ->
|
{Es, Ws} ->
|
||||||
{error,
|
{error,
|
||||||
[{File, [E || {error,E} <- Es]}],
|
[{File, [E || {error,E} <- Es]}],
|
||||||
[{File, [W || {warning,W} <- Ws]}]}
|
[{File, [W || {warning,W} <- Ws]}]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
find_forms([H|T], Tag) when element(1, H) == Tag ->
|
find_forms([H|T], Tag) when element(1, H) == Tag ->
|
||||||
@ -731,18 +728,18 @@ format_exception(Class, Reason) ->
|
|||||||
%%% @end
|
%%% @end
|
||||||
format_exception(Class, Reason, Lines) ->
|
format_exception(Class, Reason, Lines) ->
|
||||||
PrintF = fun(Term, I) ->
|
PrintF = fun(Term, I) ->
|
||||||
io_lib_pretty:print(
|
io_lib_pretty:print(
|
||||||
Term, I, columns(), ?LINEMAX, ?CHAR_MAX,
|
Term, I, columns(), ?LINEMAX, ?CHAR_MAX,
|
||||||
record_print_fun())
|
record_print_fun())
|
||||||
end,
|
end,
|
||||||
StackF = fun(_, _, _) -> false end,
|
StackF = fun(_, _, _) -> false end,
|
||||||
lines(Lines, lib:format_exception(
|
lines(Lines, lib:format_exception(
|
||||||
1, Class, Reason, erlang:get_stacktrace(), StackF, PrintF)).
|
1, Class, Reason, erlang:get_stacktrace(), StackF, PrintF)).
|
||||||
|
|
||||||
columns() ->
|
columns() ->
|
||||||
case io:columns() of
|
case io:columns() of
|
||||||
{ok, N} -> N;
|
{ok, N} -> N;
|
||||||
_-> 80
|
_-> 80
|
||||||
end.
|
end.
|
||||||
|
|
||||||
lines(infinity, S) -> S;
|
lines(infinity, S) -> S;
|
||||||
@ -804,8 +801,8 @@ recurse(Form, Else, F) ->
|
|||||||
do_transform(F, Acc, Forms, Context) ->
|
do_transform(F, Acc, Forms, Context) ->
|
||||||
Rec = fun do_transform/4, % this function
|
Rec = fun do_transform/4, % this function
|
||||||
F1 =
|
F1 =
|
||||||
fun(Form, Acc0) ->
|
fun(Form, Acc0) ->
|
||||||
{Before1, Form1, After1, Recurse, Acc1} =
|
{Before1, Form1, After1, Recurse, Acc1} =
|
||||||
this_form_rec(F, Form, Context, Acc0),
|
this_form_rec(F, Form, Context, Acc0),
|
||||||
if Recurse ->
|
if Recurse ->
|
||||||
{NewForm, NewAcc} =
|
{NewForm, NewAcc} =
|
||||||
@ -815,7 +812,7 @@ do_transform(F, Acc, Forms, Context) ->
|
|||||||
true ->
|
true ->
|
||||||
{Before1, Form1, After1, Acc1}
|
{Before1, Form1, After1, Acc1}
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
mapfoldl(F1, Acc, Forms).
|
mapfoldl(F1, Acc, Forms).
|
||||||
|
|
||||||
-spec do_depth_first(xform_f_df(), term(), forms(), #context{}) ->
|
-spec do_depth_first(xform_f_df(), term(), forms(), #context{}) ->
|
||||||
@ -825,7 +822,7 @@ do_depth_first(F, Acc, Forms, Context) ->
|
|||||||
F1 =
|
F1 =
|
||||||
fun(Form, Acc0) ->
|
fun(Form, Acc0) ->
|
||||||
{NewForm, NewAcc} =
|
{NewForm, NewAcc} =
|
||||||
enter_subtrees(Form, F, Context, Acc0, Rec),
|
enter_subtrees(Form, F, Context, Acc0, Rec),
|
||||||
this_form_df(F, NewForm, Context, NewAcc)
|
this_form_df(F, NewForm, Context, NewAcc)
|
||||||
end,
|
end,
|
||||||
mapfoldl(F1, Acc, Forms).
|
mapfoldl(F1, Acc, Forms).
|
||||||
@ -880,13 +877,13 @@ apply_F(F, Type, Form, Context, Acc) ->
|
|||||||
|
|
||||||
update_context(Form, Context0) ->
|
update_context(Form, Context0) ->
|
||||||
case type(Form) of
|
case type(Form) of
|
||||||
function ->
|
function ->
|
||||||
{Fun, Arity} =
|
{Fun, Arity} =
|
||||||
erl_syntax_lib:analyze_function(Form),
|
erl_syntax_lib:analyze_function(Form),
|
||||||
Context0#context{function = Fun,
|
Context0#context{function = Fun,
|
||||||
arity = Arity};
|
arity = Arity};
|
||||||
_ ->
|
_ ->
|
||||||
Context0
|
Context0
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@ -897,12 +894,12 @@ update_context(Form, Context0) ->
|
|||||||
%%% in question. The inserted forms are not transformed afterwards.
|
%%% in question. The inserted forms are not transformed afterwards.
|
||||||
mapfoldl(F, Accu0, [Hd|Tail]) ->
|
mapfoldl(F, Accu0, [Hd|Tail]) ->
|
||||||
{Before, Res, After, Accu1} =
|
{Before, Res, After, Accu1} =
|
||||||
case F(Hd, Accu0) of
|
case F(Hd, Accu0) of
|
||||||
{Be, _, Af, _} = Result when is_list(Be), is_list(Af) ->
|
{Be, _, Af, _} = Result when is_list(Be), is_list(Af) ->
|
||||||
Result;
|
Result;
|
||||||
{R1, A1} ->
|
{R1, A1} ->
|
||||||
{[], R1, [], A1}
|
{[], R1, [], A1}
|
||||||
end,
|
end,
|
||||||
{Rs, Accu2} = mapfoldl(F, Accu1, Tail),
|
{Rs, Accu2} = mapfoldl(F, Accu1, Tail),
|
||||||
{Before ++ [Res| After ++ Rs], Accu2};
|
{Before ++ [Res| After ++ Rs], Accu2};
|
||||||
mapfoldl(F, Accu, []) when is_function(F, 2) -> {[], Accu}.
|
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) ->
|
rpt_error(_Reason, _Fun, _Info, _Trace) ->
|
||||||
%% Fmt = lists:flatten(
|
%% Fmt = lists:flatten(
|
||||||
%% ["*** ERROR in parse_transform function:~n"
|
%% ["*** ERROR in parse_transform function:~n"
|
||||||
%% "*** Reason = ~p~n",
|
%% "*** Reason = ~p~n",
|
||||||
%% "*** Location: ~p~n",
|
%% "*** Location: ~p~n",
|
||||||
%% "*** Trace: ~p~n",
|
%% "*** Trace: ~p~n",
|
||||||
%% ["*** ~10w = ~p~n" || _ <- Info]]),
|
%% ["*** ~10w = ~p~n" || _ <- Info]]),
|
||||||
%% Args = [Reason, Fun, Trace |
|
%% Args = [Reason, Fun, Trace |
|
||||||
%% lists:foldr(
|
%% lists:foldr(
|
||||||
%% fun({K,V}, Acc) ->
|
%% fun({K,V}, Acc) ->
|
||||||
%% [K, V | Acc]
|
%% [K, V | Acc]
|
||||||
%% end, [], Info)],
|
%% end, [], Info)],
|
||||||
%%io:format(Fmt, Args),
|
%%io:format(Fmt, Args),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
@ -927,10 +924,10 @@ rpt_error(_Reason, _Fun, _Info, _Trace) ->
|
|||||||
iolist().
|
iolist().
|
||||||
format_error({E, [{M,F,A}|_]} = Error) ->
|
format_error({E, [{M,F,A}|_]} = Error) ->
|
||||||
try lists:flatten(io_lib:fwrite("~p in ~s:~s/~s", [E, atom_to_list(M),
|
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
|
catch
|
||||||
error:_ ->
|
error:_ ->
|
||||||
format_error_(Error)
|
format_error_(Error)
|
||||||
end;
|
end;
|
||||||
format_error(Error) ->
|
format_error(Error) ->
|
||||||
format_error_(Error).
|
format_error_(Error).
|
||||||
|
@ -1,33 +1,29 @@
|
|||||||
%%% The contents of this file are subject to the Erlang Public License,
|
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||||
%%% 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
|
%% This file is provided to you under the Apache License,
|
||||||
%%% http://www.erlang.org/EPLICENSE
|
%% Version 2.0 (the "License"); you may not use this file
|
||||||
%%%
|
%% except in compliance with the License. You may obtain
|
||||||
%%% Software distributed under the License is distributed on an "AS IS"
|
%% a copy of the License at
|
||||||
%%% 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
|
||||||
%%% under the License.
|
%%
|
||||||
%%%
|
%% Unless required by applicable law or agreed to in writing,
|
||||||
%%% The Original Code is exprecs-0.2.
|
%% software distributed under the License is distributed on an
|
||||||
%%%
|
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
%% KIND, either express or implied. See the License for the
|
||||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
%% specific language governing permissions and limitations
|
||||||
%%% All Rights Reserved.
|
%% under the License.
|
||||||
%%%
|
%% --------------------------------------------------
|
||||||
%%% Contributor(s): ______________________________________.
|
%% File : parse_trans_codegen.erl
|
||||||
|
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||||
|
%% @end
|
||||||
|
%%-------------------------------------------------------------------
|
||||||
|
|
||||||
%%%-------------------------------------------------------------------
|
%% @doc Parse transform for code generation pseduo functions
|
||||||
%%% File : parse_trans_codegen.erl
|
%%
|
||||||
%%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
%% <p>...</p>
|
||||||
%%% @end
|
%%
|
||||||
%%% Description :
|
%% @end
|
||||||
%%%-------------------------------------------------------------------
|
|
||||||
|
|
||||||
%%% @doc Parse transform for code generation pseduo functions
|
|
||||||
%%%
|
|
||||||
%%% <p>...</p>
|
|
||||||
%%%
|
|
||||||
%%% @end
|
|
||||||
|
|
||||||
-module(parse_trans_codegen).
|
-module(parse_trans_codegen).
|
||||||
|
|
||||||
@ -150,100 +146,100 @@
|
|||||||
parse_transform(Forms, Options) ->
|
parse_transform(Forms, Options) ->
|
||||||
Context = parse_trans:initial_context(Forms, Options),
|
Context = parse_trans:initial_context(Forms, Options),
|
||||||
{NewForms, _} =
|
{NewForms, _} =
|
||||||
parse_trans:do_depth_first(
|
parse_trans:do_depth_first(
|
||||||
fun xform_fun/4, _Acc = Forms, Forms, Context),
|
fun xform_fun/4, _Acc = Forms, Forms, Context),
|
||||||
parse_trans:return(parse_trans:revert(NewForms), Context).
|
parse_trans:return(parse_trans:revert(NewForms), Context).
|
||||||
|
|
||||||
xform_fun(application, Form, _Ctxt, Acc) ->
|
xform_fun(application, Form, _Ctxt, Acc) ->
|
||||||
MFA = erl_syntax_lib:analyze_application(Form),
|
MFA = erl_syntax_lib:analyze_application(Form),
|
||||||
L = erl_syntax:get_pos(Form),
|
L = erl_syntax:get_pos(Form),
|
||||||
case MFA of
|
case MFA of
|
||||||
{codegen, {gen_module, 3}} ->
|
{codegen, {gen_module, 3}} ->
|
||||||
[NameF, ExportsF, FunsF] =
|
[NameF, ExportsF, FunsF] =
|
||||||
erl_syntax:application_arguments(Form),
|
erl_syntax:application_arguments(Form),
|
||||||
NewForms = gen_module(NameF, ExportsF, FunsF, L, Acc),
|
NewForms = gen_module(NameF, ExportsF, FunsF, L, Acc),
|
||||||
{NewForms, Acc};
|
{NewForms, Acc};
|
||||||
{codegen, {gen_function, 2}} ->
|
{codegen, {gen_function, 2}} ->
|
||||||
[NameF, FunF] =
|
[NameF, FunF] =
|
||||||
erl_syntax:application_arguments(Form),
|
erl_syntax:application_arguments(Form),
|
||||||
NewForm = gen_function(NameF, FunF, L, L, Acc),
|
NewForm = gen_function(NameF, FunF, L, L, Acc),
|
||||||
{NewForm, Acc};
|
{NewForm, Acc};
|
||||||
{codegen, {gen_function, 3}} ->
|
{codegen, {gen_function, 3}} ->
|
||||||
[NameF, FunF, LineF] =
|
[NameF, FunF, LineF] =
|
||||||
erl_syntax:application_arguments(Form),
|
erl_syntax:application_arguments(Form),
|
||||||
NewForm = gen_function(
|
NewForm = gen_function(
|
||||||
NameF, FunF, L, erl_syntax:integer_value(LineF), Acc),
|
NameF, FunF, L, erl_syntax:integer_value(LineF), Acc),
|
||||||
{NewForm, Acc};
|
{NewForm, Acc};
|
||||||
{codegen, {gen_function_alt, 3}} ->
|
{codegen, {gen_function_alt, 3}} ->
|
||||||
[NameF, FunF, AltF] =
|
[NameF, FunF, AltF] =
|
||||||
erl_syntax:application_arguments(Form),
|
erl_syntax:application_arguments(Form),
|
||||||
NewForm = gen_function_alt(NameF, FunF, AltF, L, L, Acc),
|
NewForm = gen_function_alt(NameF, FunF, AltF, L, L, Acc),
|
||||||
{NewForm, Acc};
|
{NewForm, Acc};
|
||||||
{codegen, {gen_functions, 1}} ->
|
{codegen, {gen_functions, 1}} ->
|
||||||
[List] = erl_syntax:application_arguments(Form),
|
[List] = erl_syntax:application_arguments(Form),
|
||||||
Elems = erl_syntax:list_elements(List),
|
Elems = erl_syntax:list_elements(List),
|
||||||
NewForms = lists:map(
|
NewForms = lists:map(
|
||||||
fun(E) ->
|
fun(E) ->
|
||||||
[NameF, FunF] = erl_syntax:tuple_elements(E),
|
[NameF, FunF] = erl_syntax:tuple_elements(E),
|
||||||
gen_function(NameF, FunF, L, L, Acc)
|
gen_function(NameF, FunF, L, L, Acc)
|
||||||
end, Elems),
|
end, Elems),
|
||||||
{erl_syntax:list(NewForms), Acc};
|
{erl_syntax:list(NewForms), Acc};
|
||||||
{codegen, {exprs, 1}} ->
|
{codegen, {exprs, 1}} ->
|
||||||
[FunF] = erl_syntax:application_arguments(Form),
|
[FunF] = erl_syntax:application_arguments(Form),
|
||||||
[Clause] = erl_syntax:fun_expr_clauses(FunF),
|
[Clause] = erl_syntax:fun_expr_clauses(FunF),
|
||||||
[{clause,_,_,_,Body}] = parse_trans:revert([Clause]),
|
[{clause,_,_,_,Body}] = parse_trans:revert([Clause]),
|
||||||
NewForm = substitute(erl_parse:abstract(Body)),
|
NewForm = substitute(erl_parse:abstract(Body)),
|
||||||
{NewForm, Acc};
|
{NewForm, Acc};
|
||||||
_ ->
|
_ ->
|
||||||
{Form, Acc}
|
{Form, Acc}
|
||||||
end;
|
end;
|
||||||
xform_fun(_, Form, _Ctxt, Acc) ->
|
xform_fun(_, Form, _Ctxt, Acc) ->
|
||||||
{Form, Acc}.
|
{Form, Acc}.
|
||||||
|
|
||||||
gen_module(NameF, ExportsF, FunsF, L, Acc) ->
|
gen_module(NameF, ExportsF, FunsF, L, Acc) ->
|
||||||
case erl_syntax:type(FunsF) of
|
case erl_syntax:type(FunsF) of
|
||||||
list ->
|
list ->
|
||||||
try gen_module_(NameF, ExportsF, FunsF, L, Acc)
|
try gen_module_(NameF, ExportsF, FunsF, L, Acc)
|
||||||
catch
|
catch
|
||||||
error:E ->
|
error:E ->
|
||||||
ErrStr = parse_trans:format_exception(error, E),
|
ErrStr = parse_trans:format_exception(error, E),
|
||||||
{error, {L, ?MODULE, ErrStr}}
|
{error, {L, ?MODULE, ErrStr}}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ErrStr = parse_trans:format_exception(
|
ErrStr = parse_trans:format_exception(
|
||||||
error, "Argument must be a list"),
|
error, "Argument must be a list"),
|
||||||
{error, {L, ?MODULE, ErrStr}}
|
{error, {L, ?MODULE, ErrStr}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
gen_module_(NameF, ExportsF, FunsF, L0, Acc) ->
|
gen_module_(NameF, ExportsF, FunsF, L0, Acc) ->
|
||||||
P = erl_syntax:get_pos(NameF),
|
P = erl_syntax:get_pos(NameF),
|
||||||
ModF = case parse_trans:revert_form(NameF) of
|
ModF = case parse_trans:revert_form(NameF) of
|
||||||
{atom,_,_} = Am -> Am;
|
{atom,_,_} = Am -> Am;
|
||||||
{tuple,_,[{atom,_,'$var'},
|
{tuple,_,[{atom,_,'$var'},
|
||||||
{var,_,V}]} ->
|
{var,_,V}]} ->
|
||||||
{var,P,V}
|
{var,P,V}
|
||||||
end,
|
end,
|
||||||
cons(
|
cons(
|
||||||
{cons,P,
|
{cons,P,
|
||||||
{tuple,P,
|
{tuple,P,
|
||||||
[{atom,P,attribute},
|
[{atom,P,attribute},
|
||||||
{integer,P,1},
|
{integer,P,1},
|
||||||
{atom,P,module},
|
{atom,P,module},
|
||||||
ModF]},
|
ModF]},
|
||||||
substitute(
|
substitute(
|
||||||
abstract(
|
abstract(
|
||||||
[{attribute,P,export,
|
[{attribute,P,export,
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(TupleF) ->
|
fun(TupleF) ->
|
||||||
[F,A] = erl_syntax:tuple_elements(TupleF),
|
[F,A] = erl_syntax:tuple_elements(TupleF),
|
||||||
{erl_syntax:atom_value(F), erl_syntax:integer_value(A)}
|
{erl_syntax:atom_value(F), erl_syntax:integer_value(A)}
|
||||||
end, erl_syntax:list_elements(ExportsF))}]))},
|
end, erl_syntax:list_elements(ExportsF))}]))},
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(FTupleF) ->
|
fun(FTupleF) ->
|
||||||
Pos = erl_syntax:get_pos(FTupleF),
|
Pos = erl_syntax:get_pos(FTupleF),
|
||||||
[FName, FFunF] = erl_syntax:tuple_elements(FTupleF),
|
[FName, FFunF] = erl_syntax:tuple_elements(FTupleF),
|
||||||
gen_function(FName, FFunF, L0, Pos, Acc)
|
gen_function(FName, FFunF, L0, Pos, Acc)
|
||||||
end, erl_syntax:list_elements(FunsF))).
|
end, erl_syntax:list_elements(FunsF))).
|
||||||
|
|
||||||
cons({cons,L,H,T}, L2) ->
|
cons({cons,L,H,T}, L2) ->
|
||||||
{cons,L,H,cons(T, L2)};
|
{cons,L,H,cons(T, L2)};
|
||||||
@ -258,80 +254,80 @@ cons({nil,L}, []) ->
|
|||||||
gen_function(NameF, FunF, L0, L, Acc) ->
|
gen_function(NameF, FunF, L0, L, Acc) ->
|
||||||
try gen_function_(NameF, FunF, [], L, Acc)
|
try gen_function_(NameF, FunF, [], L, Acc)
|
||||||
catch
|
catch
|
||||||
error:E ->
|
error:E ->
|
||||||
ErrStr = parse_trans:format_exception(error, E),
|
ErrStr = parse_trans:format_exception(error, E),
|
||||||
{error, {L0, ?MODULE, ErrStr}}
|
{error, {L0, ?MODULE, ErrStr}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
gen_function_alt(NameF, FunF, AltF, L0, L, Acc) ->
|
gen_function_alt(NameF, FunF, AltF, L0, L, Acc) ->
|
||||||
try gen_function_(NameF, FunF, AltF, L, Acc)
|
try gen_function_(NameF, FunF, AltF, L, Acc)
|
||||||
catch
|
catch
|
||||||
error:E ->
|
error:E ->
|
||||||
ErrStr = parse_trans:format_exception(error, E),
|
ErrStr = parse_trans:format_exception(error, E),
|
||||||
{error, {L0, ?MODULE, ErrStr}}
|
{error, {L0, ?MODULE, ErrStr}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
gen_function_(NameF, FunF, AltF, L, Acc) ->
|
gen_function_(NameF, FunF, AltF, L, Acc) ->
|
||||||
case erl_syntax:type(FunF) of
|
case erl_syntax:type(FunF) of
|
||||||
T when T==implicit_fun; T==fun_expr ->
|
T when T==implicit_fun; T==fun_expr ->
|
||||||
{Arity, Clauses} = gen_function_clauses(T, NameF, FunF, L, Acc),
|
{Arity, Clauses} = gen_function_clauses(T, NameF, FunF, L, Acc),
|
||||||
{tuple, 1, [{atom, 1, function},
|
{tuple, 1, [{atom, 1, function},
|
||||||
{integer, 1, L},
|
{integer, 1, L},
|
||||||
NameF,
|
NameF,
|
||||||
{integer, 1, Arity},
|
{integer, 1, Arity},
|
||||||
substitute(abstract(Clauses))]};
|
substitute(abstract(Clauses))]};
|
||||||
list_comp ->
|
list_comp ->
|
||||||
%% Extract the fun from the LC
|
%% Extract the fun from the LC
|
||||||
[Template] = parse_trans:revert(
|
[Template] = parse_trans:revert(
|
||||||
[erl_syntax:list_comp_template(FunF)]),
|
[erl_syntax:list_comp_template(FunF)]),
|
||||||
%% Process fun in the normal fashion (as above)
|
%% Process fun in the normal fashion (as above)
|
||||||
{Arity, Clauses} = gen_function_clauses(erl_syntax:type(Template),
|
{Arity, Clauses} = gen_function_clauses(erl_syntax:type(Template),
|
||||||
NameF, Template, L, Acc),
|
NameF, Template, L, Acc),
|
||||||
Body = erl_syntax:list_comp_body(FunF),
|
Body = erl_syntax:list_comp_body(FunF),
|
||||||
%% Collect all variables from the LC generator(s)
|
%% Collect all variables from the LC generator(s)
|
||||||
%% We want to produce an abstract representation of something like:
|
%% We want to produce an abstract representation of something like:
|
||||||
%% {function,1,Name,Arity,
|
%% {function,1,Name,Arity,
|
||||||
%% lists:flatten(
|
%% lists:flatten(
|
||||||
%% [(fun(V1,V2,...) ->
|
%% [(fun(V1,V2,...) ->
|
||||||
%% ...
|
%% ...
|
||||||
%% end)(__V1,__V2,...) || {__V1,__V2,...} <- L])}
|
%% end)(__V1,__V2,...) || {__V1,__V2,...} <- L])}
|
||||||
%% where the __Vn vars are our renamed versions of the LC generator
|
%% where the __Vn vars are our renamed versions of the LC generator
|
||||||
%% vars. This allows us to instantiate the clauses at run-time.
|
%% vars. This allows us to instantiate the clauses at run-time.
|
||||||
Vars = lists:flatten(
|
Vars = lists:flatten(
|
||||||
[sets:to_list(erl_syntax_lib:variables(
|
[sets:to_list(erl_syntax_lib:variables(
|
||||||
erl_syntax:generator_pattern(G)))
|
erl_syntax:generator_pattern(G)))
|
||||||
|| G <- Body]),
|
|| G <- Body]),
|
||||||
Vars1 = [list_to_atom("__" ++ atom_to_list(V)) || V <- Vars],
|
Vars1 = [list_to_atom("__" ++ atom_to_list(V)) || V <- Vars],
|
||||||
VarMap = lists:zip(Vars, Vars1),
|
VarMap = lists:zip(Vars, Vars1),
|
||||||
Body1 =
|
Body1 =
|
||||||
[erl_syntax:generator(
|
[erl_syntax:generator(
|
||||||
rename_vars(VarMap, gen_pattern(G)),
|
rename_vars(VarMap, gen_pattern(G)),
|
||||||
gen_body(G)) || G <- Body],
|
gen_body(G)) || G <- Body],
|
||||||
[RevLC] = parse_trans:revert(
|
[RevLC] = parse_trans:revert(
|
||||||
[erl_syntax:list_comp(
|
[erl_syntax:list_comp(
|
||||||
{call, 1,
|
{call, 1,
|
||||||
{'fun',1,
|
{'fun',1,
|
||||||
{clauses,
|
{clauses,
|
||||||
[{clause,1,[{var,1,V} || V <- Vars],[],
|
[{clause,1,[{var,1,V} || V <- Vars],[],
|
||||||
[substitute(
|
[substitute(
|
||||||
abstract(Clauses))]
|
abstract(Clauses))]
|
||||||
}]}
|
}]}
|
||||||
}, [{var,1,V} || V <- Vars1]}, Body1)]),
|
}, [{var,1,V} || V <- Vars1]}, Body1)]),
|
||||||
AltC = case AltF of
|
AltC = case AltF of
|
||||||
[] -> {nil,1};
|
[] -> {nil,1};
|
||||||
_ ->
|
_ ->
|
||||||
{Arity, AltC1} = gen_function_clauses(
|
{Arity, AltC1} = gen_function_clauses(
|
||||||
erl_syntax:type(AltF),
|
erl_syntax:type(AltF),
|
||||||
NameF, AltF, L, Acc),
|
NameF, AltF, L, Acc),
|
||||||
substitute(abstract(AltC1))
|
substitute(abstract(AltC1))
|
||||||
end,
|
end,
|
||||||
{tuple,1,[{atom,1,function},
|
{tuple,1,[{atom,1,function},
|
||||||
{integer, 1, L},
|
{integer, 1, L},
|
||||||
NameF,
|
NameF,
|
||||||
{integer, 1, Arity},
|
{integer, 1, Arity},
|
||||||
{call, 1, {remote, 1, {atom, 1, lists},
|
{call, 1, {remote, 1, {atom, 1, lists},
|
||||||
{atom,1,flatten}},
|
{atom,1,flatten}},
|
||||||
[{op, 1, '++', RevLC, AltC}]}]}
|
[{op, 1, '++', RevLC, AltC}]}]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
gen_pattern(G) ->
|
gen_pattern(G) ->
|
||||||
@ -343,21 +339,21 @@ gen_body(G) ->
|
|||||||
rename_vars(Vars, Tree) ->
|
rename_vars(Vars, Tree) ->
|
||||||
erl_syntax_lib:map(
|
erl_syntax_lib:map(
|
||||||
fun(T) ->
|
fun(T) ->
|
||||||
case erl_syntax:type(T) of
|
case erl_syntax:type(T) of
|
||||||
variable ->
|
variable ->
|
||||||
V = erl_syntax:variable_name(T),
|
V = erl_syntax:variable_name(T),
|
||||||
{_,V1} = lists:keyfind(V,1,Vars),
|
{_,V1} = lists:keyfind(V,1,Vars),
|
||||||
erl_syntax:variable(V1);
|
erl_syntax:variable(V1);
|
||||||
_ ->
|
_ ->
|
||||||
T
|
T
|
||||||
end
|
end
|
||||||
end, Tree).
|
end, Tree).
|
||||||
|
|
||||||
gen_function_clauses(implicit_fun, _NameF, FunF, _L, Acc) ->
|
gen_function_clauses(implicit_fun, _NameF, FunF, _L, Acc) ->
|
||||||
AQ = erl_syntax:implicit_fun_name(FunF),
|
AQ = erl_syntax:implicit_fun_name(FunF),
|
||||||
Name = erl_syntax:atom_value(erl_syntax:arity_qualifier_body(AQ)),
|
Name = erl_syntax:atom_value(erl_syntax:arity_qualifier_body(AQ)),
|
||||||
Arity = erl_syntax:integer_value(
|
Arity = erl_syntax:integer_value(
|
||||||
erl_syntax:arity_qualifier_argument(AQ)),
|
erl_syntax:arity_qualifier_argument(AQ)),
|
||||||
NewForm = find_function(Name, Arity, Acc),
|
NewForm = find_function(Name, Arity, Acc),
|
||||||
ClauseForms = erl_syntax:function_clauses(NewForm),
|
ClauseForms = erl_syntax:function_clauses(NewForm),
|
||||||
{Arity, ClauseForms};
|
{Arity, ClauseForms};
|
||||||
@ -368,32 +364,32 @@ gen_function_clauses(fun_expr, _NameF, FunF, _L, _Acc) ->
|
|||||||
|
|
||||||
find_function(Name, Arity, Forms) ->
|
find_function(Name, Arity, Forms) ->
|
||||||
[Form] = [F || {function,_,N,A,_} = F <- Forms,
|
[Form] = [F || {function,_,N,A,_} = F <- Forms,
|
||||||
N == Name,
|
N == Name,
|
||||||
A == Arity],
|
A == Arity],
|
||||||
Form.
|
Form.
|
||||||
|
|
||||||
abstract(ClauseForms) ->
|
abstract(ClauseForms) ->
|
||||||
erl_parse:abstract(parse_trans:revert(ClauseForms)).
|
erl_parse:abstract(parse_trans:revert(ClauseForms)).
|
||||||
|
|
||||||
substitute({tuple,L0,
|
substitute({tuple,L0,
|
||||||
[{atom,_,tuple},
|
[{atom,_,tuple},
|
||||||
{integer,_,L},
|
{integer,_,L},
|
||||||
{cons,_,
|
{cons,_,
|
||||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$var'}]},
|
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$var'}]},
|
||||||
{cons,_,
|
{cons,_,
|
||||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,V}]},
|
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,V}]},
|
||||||
{nil,_}}}]}) ->
|
{nil,_}}}]}) ->
|
||||||
{call, L0, {remote,L0,{atom,L0,erl_parse},
|
{call, L0, {remote,L0,{atom,L0,erl_parse},
|
||||||
{atom,L0,abstract}},
|
{atom,L0,abstract}},
|
||||||
[{var, L0, V}, {integer, L0, L}]};
|
[{var, L0, V}, {integer, L0, L}]};
|
||||||
substitute({tuple,L0,
|
substitute({tuple,L0,
|
||||||
[{atom,_,tuple},
|
[{atom,_,tuple},
|
||||||
{integer,_,_},
|
{integer,_,_},
|
||||||
{cons,_,
|
{cons,_,
|
||||||
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$form'}]},
|
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$form'}]},
|
||||||
{cons,_,
|
{cons,_,
|
||||||
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,F}]},
|
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,F}]},
|
||||||
{nil,_}}}]}) ->
|
{nil,_}}}]}) ->
|
||||||
{var, L0, F};
|
{var, L0, F};
|
||||||
substitute([]) ->
|
substitute([]) ->
|
||||||
[];
|
[];
|
||||||
@ -407,17 +403,17 @@ substitute(X) ->
|
|||||||
get_arity(Clauses) ->
|
get_arity(Clauses) ->
|
||||||
Ays = [length(erl_syntax:clause_patterns(C)) || C <- Clauses],
|
Ays = [length(erl_syntax:clause_patterns(C)) || C <- Clauses],
|
||||||
case lists:usort(Ays) of
|
case lists:usort(Ays) of
|
||||||
[Ay] ->
|
[Ay] ->
|
||||||
Ay;
|
Ay;
|
||||||
Other ->
|
Other ->
|
||||||
erlang:error(ambiguous, Other)
|
erlang:error(ambiguous, Other)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
format_error(E) ->
|
format_error(E) ->
|
||||||
case io_lib:deep_char_list(E) of
|
case io_lib:deep_char_list(E) of
|
||||||
true ->
|
true ->
|
||||||
E;
|
E;
|
||||||
_ ->
|
_ ->
|
||||||
io_lib:write(E)
|
io_lib:write(E)
|
||||||
end.
|
end.
|
||||||
|
@ -41,14 +41,14 @@ transform_module(Mod, PT, Options) ->
|
|||||||
Forms = abstract_code(File),
|
Forms = abstract_code(File),
|
||||||
Context = parse_trans:initial_context(Forms, Options),
|
Context = parse_trans:initial_context(Forms, Options),
|
||||||
PTMods = if is_atom(PT) -> [PT];
|
PTMods = if is_atom(PT) -> [PT];
|
||||||
is_function(PT, 2) -> [PT];
|
is_function(PT, 2) -> [PT];
|
||||||
is_list(PT) -> PT
|
is_list(PT) -> PT
|
||||||
end,
|
end,
|
||||||
Transformed = lists:foldl(fun(PTx, Fs) when is_function(PTx, 2) ->
|
Transformed = lists:foldl(fun(PTx, Fs) when is_function(PTx, 2) ->
|
||||||
PTx(Fs, Options);
|
PTx(Fs, Options);
|
||||||
(PTMod, Fs) ->
|
(PTMod, Fs) ->
|
||||||
PTMod:parse_transform(Fs, Options)
|
PTMod:parse_transform(Fs, Options)
|
||||||
end, Forms, PTMods),
|
end, Forms, PTMods),
|
||||||
parse_trans:optionally_pretty_print(Transformed, Options, Context),
|
parse_trans:optionally_pretty_print(Transformed, Options, Context),
|
||||||
compile_and_load_forms(Transformed, get_compile_options(Options)).
|
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,
|
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||||
%%% 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
|
%% This file is provided to you under the Apache License,
|
||||||
%%% http://www.erlang.org/EPLICENSE
|
%% Version 2.0 (the "License"); you may not use this file
|
||||||
%%%
|
%% except in compliance with the License. You may obtain
|
||||||
%%% Software distributed under the License is distributed on an "AS IS"
|
%% a copy of the License at
|
||||||
%%% 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
|
||||||
%%% under the License.
|
%%
|
||||||
%%%
|
%% Unless required by applicable law or agreed to in writing,
|
||||||
%%% The Original Code is exprecs-0.2.
|
%% software distributed under the License is distributed on an
|
||||||
%%%
|
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
%%% The Initial Developer of the Original Code is Ericsson AB.
|
%% KIND, either express or implied. See the License for the
|
||||||
%%% Portions created by Ericsson are Copyright (C), 2006, Ericsson AB.
|
%% specific language governing permissions and limitations
|
||||||
%%% All Rights Reserved.
|
%% under the License.
|
||||||
%%%
|
%% --------------------------------------------------
|
||||||
%%% Contributor(s): ______________________________________.
|
%% File : parse_trans_pp.erl
|
||||||
|
%% @author : Ulf Wiger <ulf@wiger.net>
|
||||||
|
%% @end
|
||||||
|
%% Description :
|
||||||
|
%%
|
||||||
|
%% Created : 3 Aug 2010 by Ulf Wiger <ulf@wiger.net>
|
||||||
|
%% --------------------------------------------------
|
||||||
|
|
||||||
%%%-------------------------------------------------------------------
|
%% @doc Generic parse transform library for Erlang.
|
||||||
%%% File : parse_trans_pp.erl
|
%%
|
||||||
%%% @author : Ulf Wiger <ulf@feuerlabs.com>
|
%% This module contains some useful utility functions for inspecting
|
||||||
%%% @end
|
%% the results of parse transforms or code generation.
|
||||||
%%% Description :
|
%% 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.
|
||||||
%%% Created : 3 Aug 2010 by Ulf Wiger <ulf@feuerlabs.com>
|
%%
|
||||||
%%%-------------------------------------------------------------------
|
%% Using e.g. the following bash alias:
|
||||||
|
%% <pre>
|
||||||
%%% @doc Generic parse transform library for Erlang.
|
%% alias pp='escript $PARSE_TRANS_ROOT/ebin/parse_trans_pp.beam'
|
||||||
%%%
|
|
||||||
%%% 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>
|
%%% </pre>
|
||||||
%%% a file could be pretty-printed using the following command:
|
%% a file could be pretty-printed using the following command:
|
||||||
%%%
|
%%
|
||||||
%%% `$ pp ex_codegen.beam | less'
|
%% `$ pp ex_codegen.beam | less'
|
||||||
%%% @end
|
%% @end
|
||||||
|
|
||||||
-module(parse_trans_pp).
|
-module(parse_trans_pp).
|
||||||
|
|
||||||
@ -103,13 +100,13 @@ pp_beam(F, Out) ->
|
|||||||
pp_beam_to_str(F) ->
|
pp_beam_to_str(F) ->
|
||||||
case beam_lib:chunks(F, [abstract_code]) of
|
case beam_lib:chunks(F, [abstract_code]) of
|
||||||
{ok, {_, [{abstract_code,{_,AC0}}]}} ->
|
{ok, {_, [{abstract_code,{_,AC0}}]}} ->
|
||||||
AC = epp:restore_typed_record_fields(AC0),
|
AC = epp:restore_typed_record_fields(AC0),
|
||||||
{ok, lists:flatten(
|
{ok, lists:flatten(
|
||||||
%% io_lib:fwrite("~s~n", [erl_prettypr:format(
|
%% io_lib:fwrite("~s~n", [erl_prettypr:format(
|
||||||
%% erl_syntax:form_list(AC))])
|
%% erl_syntax:form_list(AC))])
|
||||||
io_lib:fwrite("~s~n", [lists:flatten(
|
io_lib:fwrite("~s~n", [lists:flatten(
|
||||||
[erl_pp:form(Form) ||
|
[erl_pp:form(Form) ||
|
||||||
Form <- AC])])
|
Form <- AC])])
|
||||||
)};
|
)};
|
||||||
Other ->
|
Other ->
|
||||||
{error, Other}
|
{error, Other}
|
||||||
|
Loading…
Reference in New Issue
Block a user