erl_pp.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 838 行 · 第 1/2 页

ERL
838
字号
%% ``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 should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% 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 Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id $%%-module(erl_pp).%%% Pretty printer for Erlang code in the same format as returned from%%% the parser. It does not always produce pretty code.-export([form/1,form/2,	 attribute/1,attribute/2,function/1,function/2,rule/1,rule/2,	 guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4]).%% The following exports are here for backwards compatibility.-export([seq/1,seq/2]).-deprecated([{seq,1},{seq,2}]).-import(lists, [append/1,foldr/3,mapfoldl/3,reverse/1,reverse/2]).-import(io_lib, [write/1,format/2,write_char/1,write_string/1]).-import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).-define(MAXLINE, 72).%%%%%% Exported functions%%%seq(Es) ->    exprs(Es).seq(Es, Hook) ->    exprs(Es, Hook).form(Thing) ->    form(Thing, none).form(Thing, Hook) ->    frmt(lform(Thing, Hook)).attribute(Thing) ->    attribute(Thing, none).attribute(Thing, Hook) ->    frmt(lattribute(Thing, Hook)).function(F) ->    function(F, none).function(F, Hook) ->    frmt(lfunction(F, Hook)).rule(R) ->    rule(R, none).rule(R, Hook) ->    frmt(lrule(R, Hook)).guard(Gs) ->    guard(Gs, none).guard(Gs, Hook) ->    frmt(lguard(Gs, Hook)).exprs(Es) ->    exprs(Es, 0, none).exprs(Es, Hook) ->    exprs(Es, 0, Hook).exprs(Es, I, Hook) ->    frmt({seq,[],[],[$,],lexprs(Es, Hook)}, I).expr(E) ->    frmt(lexpr(E, 0, none)).expr(E, Hook) ->    frmt(lexpr(E, 0, Hook)).expr(E, I, Hook) ->    frmt(lexpr(E, 0, Hook), I).expr(E, I, P, Hook) ->    frmt(lexpr(E, P, Hook), I).%%%%%% Local functions%%%lform({attribute,Line,Name,Arg}, Hook) ->    lattribute({attribute,Line,Name,Arg}, Hook);lform({function,Line,Name,Arity,Clauses}, Hook) ->    lfunction({function,Line,Name,Arity,Clauses}, Hook);lform({rule,Line,Name,Arity,Clauses}, Hook) ->    lrule({rule,Line,Name,Arity,Clauses}, Hook);%% These are specials to make it easier for the compiler.lform({error,E}, _Hook) ->    leaf(format("~p\n", [{error,E}]));lform({warning,W}, _Hook) ->    leaf(format("~p\n", [{warning,W}]));lform({eof,_Line}, _Hook) ->    $\n.lattribute({attribute,_Line,Name,Arg}, Hook) ->    [lattribute(Name, Arg, Hook),leaf(".\n")].lattribute(module, {M,Vs}, _Hook) ->    attr("module",[{var,0,pname(M)},                   foldr(fun(V, C) -> {cons,0,{var,0,V},C}                          end, {nil,0}, Vs)]);lattribute(module, M, _Hook) ->    attr("module", [{var,0,pname(M)}]);lattribute(export, Falist, _Hook) ->    call({var,0,"-export"}, [falist(Falist)], 0, none);lattribute(import, Name, _Hook) when is_list(Name) ->    attr("import", [{var,0,pname(Name)}]);lattribute(import, {From,Falist}, _Hook) ->    attr("import",[{var,0,pname(From)},falist(Falist)]);lattribute(file, {Name,Line}, _Hook) ->    attr("file", [{var,0,format("~p", [Name])},{integer,0,Line}]);lattribute(record, {Name,Is}, Hook) ->    Nl = leaf(format("-record(~w,", [Name])),    [{first,Nl,record_fields(Is, Hook)},$)];lattribute(Name, Arg, _Hook) ->    attr(write(Name), [erl_parse:abstract(Arg)]).attr(Name, Args) ->    call({var,0,format("-~s", [Name])}, Args, 0, none).pname(['' | As]) ->    [$. | pname(As)];pname([A]) ->    write(A);pname([A | As]) ->    [write(A),$.|pname(As)];pname(A) when is_atom(A) ->    write(A).falist([]) ->    {nil,0};falist([{Name,Arity}|Falist]) ->    {cons,0,{var,0,format("~w/~w", [Name,Arity])},falist(Falist)}.lfunction({function,_Line,Name,_Arity,Cs}, Hook) ->    Cll = nl_clauses(fun (C, H) -> func_clause(Name, C, H) end, $;, Hook, Cs),    [Cll,leaf(".\n")].func_clause(Name, {clause,Line,Head,Guard,Body}, Hook) ->    Hl = call({atom,Line,Name}, Head, 0, Hook),    Gl = guard_when(Hl, Guard, Hook),    Bl = body(Body, Hook),    {step,Gl,Bl}.lrule({rule,_Line,Name,_Arity,Cs}, Hook) ->    Cll = nl_clauses(fun (C, H) -> rule_clause(Name, C, H) end, $;, Hook, Cs),    [Cll,leaf(".\n")].rule_clause(Name, {clause,Line,Head,Guard,Body}, Hook) ->    Hl = call({atom,Line,Name}, Head, 0, Hook),    Gl = guard_when(Hl, Guard, Hook, leaf(" :-")),    Bl = rule_body(Body, Hook),    {step,Gl,Bl}.rule_body(Es, Hook) ->    lc_quals(Es, Hook).guard_when(Before, Guard, Hook) ->    guard_when(Before, Guard, Hook, ' ->').guard_when(Before, Guard, Hook, After) ->    Gl = lguard(Guard, Hook),    [{list,[{step,Before,Gl}]},After].lguard([E|Es], Hook) when is_list(E) ->    {list,[{step,'when',expr_list([E|Es], [$;], fun guard0/2, Hook)}]};lguard([E|Es], Hook) -> % before R6    lguard([[E|Es]], Hook);lguard([], _) ->    [].guard0(Es, Hook) ->    expr_list(Es, [$,], fun lexpr/2, Hook).%% body(Before, Es, Hook) -> [Char].body([E], Hook) ->    lexpr(E, Hook);body(Es, Hook) ->    {prefer_nl,[$,],lexprs(Es, Hook)}.lexpr(E, Hook) ->    lexpr(E, 0, Hook).lexpr({var,_,V}, _, _) when is_integer(V) ->	%Special hack for Robert    leaf(format("_~w", [V]));lexpr({var,_,V}, _, _) -> leaf(format("~s", [V]));lexpr({char,_,C}, _, _) -> leaf(write_char(C));lexpr({integer,_,N}, _, _) -> leaf(write(N));lexpr({float,_,F}, _, _) -> leaf(write(F));lexpr({atom,_,A}, _, _) -> leaf(write(A));lexpr({string,_,S}, _, _) -> {string,S};lexpr({nil,_}, _, _) -> '[]';lexpr({cons,_,H,T}, _, Hook) ->    list(T, [H], Hook);lexpr({lc,_,E,Qs}, _Prec, Hook) ->    Lcl = {list,[{step,[lexpr(E, Hook),leaf(" ||")],lc_quals(Qs, Hook)}]},    {seq,$[,$],[],[Lcl]};lexpr({tuple,_,Elts}, _, Hook) ->    tuple(Elts, Hook);%%lexpr({struct,_,Tag,Elts}, _, Hook) ->%%  {first,format("~w", [Tag]),tuple(Elts, Hook)};lexpr({record_index, _, Name, F}, Prec, Hook) ->    {P,R} = preop_prec('#'),    Nl = leaf(format("#~w", [Name])),    El = [Nl,$.,lexpr(F, R, Hook)],    maybe_paren(P, Prec, El);lexpr({record, _, Name, Fs}, Prec, Hook) ->    {P,_R} = preop_prec('#'),    Nl = leaf(format("#~w", [Name])),    El = {first,Nl,record_fields(Fs, Hook)},    maybe_paren(P, Prec, El);lexpr({record_field, _, Rec, Name, F}, Prec, Hook) ->    {L,P,R} = inop_prec('#'),    Rl = lexpr(Rec, L, Hook),    Nl = leaf(format("#~w.", [Name])),    El = [Rl,Nl,lexpr(F, R, Hook)],    maybe_paren(P, Prec, El);lexpr({record, _, Rec, Name, Fs}, Prec, Hook) ->    {L,P,_R} = inop_prec('#'),    Rl = lexpr(Rec, L, Hook),    Nl = leaf(format("#~w", [Name])),    El = {first,[Rl,Nl],record_fields(Fs, Hook)},    maybe_paren(P, Prec, El);lexpr({record_field, _, {atom,_,''}, F}, Prec, Hook) ->    {_L,P,R} = inop_prec('.'),    El = [$.,lexpr(F, R, Hook)],    maybe_paren(P, Prec, El);lexpr({record_field, _, Rec, F}, Prec, Hook) ->    {L,P,R} = inop_prec('.'),    El = [lexpr(Rec, L, Hook),$.,lexpr(F, R, Hook)],    maybe_paren(P, Prec, El);lexpr({block,_,Es}, _, Hook) ->    {list,[{step,'begin',body(Es, Hook)},'end']};lexpr({'if',_,Cs}, _, Hook) ->    {list,[{step,'if',if_clauses(Cs, Hook)},'end']};lexpr({'case',_,Expr,Cs}, _, Hook) ->    {list,[{step,{list,[{step,'case',lexpr(Expr, Hook)},'of']},            cr_clauses(Cs, Hook)},           'end']};lexpr({'cond',_,Cs}, _, Hook) ->    {list,[{step,leaf("cond"),cond_clauses(Cs, Hook)},'end']};lexpr({'receive',_,Cs}, _, Hook) ->    {list,[{step,'receive',cr_clauses(Cs, Hook)},'end']};lexpr({'receive',_,Cs,To,ToOpt}, _, Hook) ->    Al = {list,[{step,[lexpr(To, Hook),' ->'],body(ToOpt, Hook)}]},    {list,[{step,'receive',cr_clauses(Cs, Hook)},           {step,'after',Al},           'end']};lexpr({'fun',_,{function,F,A}}, _Prec, _Hook) ->    leaf(format("fun ~w/~w", [F,A]));lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Hook) ->    {force_nl,fun_info(Extra),leaf(format("fun ~w/~w", [F,A]))};lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook) ->    leaf(format("fun ~w:~w/~w", [M,F,A]));lexpr({'fun',_,{clauses,Cs}}, _Prec, Hook) ->    {list,[{first,'fun',fun_clauses(Cs, Hook)},'end']};lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Hook) ->    {force_nl,fun_info(Extra),     {list,[{first,'fun',fun_clauses(Cs, Hook)},'end']}};lexpr({'query',_,Lc}, _Prec, Hook) ->    {list,[{step,leaf("query"),lexpr(Lc, 0, Hook)},'end']};lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Hook) ->    case erl_internal:bif(M, F, length(Args)) of        true ->            call(N, Args, Prec, Hook);        false ->            call(Name, Args, Prec, Hook)    end;lexpr({call,_,Name,Args}, Prec, Hook) ->    call(Name, Args, Prec, Hook);lexpr({'try',_,Es,Scs,Ccs,As}, _, Hook) ->    {list,[if               Scs =:= [] ->                   {step,'try',body(Es, Hook)};               true ->                   {step,{list,[{step,'try',body(Es, Hook)},'of']},                    cr_clauses(Scs, Hook)}           end,           if               Ccs =:= [] ->                   [];               true ->                   {step,'catch',try_clauses(Ccs, Hook)}           end,           if               As =:= [] ->                   [];               true ->                   {step,'after',body(As, Hook)}           end,           'end']};lexpr({'catch',_,Expr}, Prec, Hook) ->    {P,R} = preop_prec('catch'),    El = {list,[{step,'catch',lexpr(Expr, R, Hook)}]},    maybe_paren(P, Prec, El);lexpr({match,_,Lhs,Rhs}, Prec, Hook) ->    {L,P,R} = inop_prec('='),    Pl = lexpr(Lhs, L, Hook),    Rl = lexpr(Rhs, R, Hook),    El = {list,[{cstep,[Pl,' ='],Rl}]},    maybe_paren(P, Prec, El);lexpr({op,_,Op,Arg}, Prec, Hook) ->    {P,R} = preop_prec(Op),    Ol = leaf(format("~s ", [Op])),    El = [Ol,lexpr(Arg, R, Hook)],    maybe_paren(P, Prec, El);lexpr({op,_,Op,Larg,Rarg}, Prec, Hook) ->    {L,P,R} = inop_prec(Op),    Ll = lexpr(Larg, L, Hook),    Ol = leaf(format("~s", [Op])),    Lr = lexpr(Rarg, R, Hook),    El = {list,[Ll,Ol,Lr]},    maybe_paren(P, Prec, El);%% Special expressions which are not really legal everywhere.lexpr({remote,_,M,F}, Prec, Hook) ->    {L,P,R} = inop_prec(':'),    NameItem = lexpr(M, L, Hook),    CallItem = lexpr(F, R, Hook),    maybe_paren(P, Prec, [NameItem,$:,CallItem]);%% BIT SYNTAX:lexpr({bin,_,Fs}, _, Hook) ->    bit_grp(Fs, Hook);%% Special case for straight values.lexpr({value,_,Val}, _,_) ->    leaf(write(Val));%% Now do the hook.lexpr(Other, _Precedence, none) ->    leaf(format("INVALID-FORM:~w:",[Other]));lexpr(HookExpr, Precedence, {Mod,Func,Eas}) when Mod =/= 'fun' ->    {ehook,HookExpr,Precedence,{Mod,Func,Eas}};lexpr(HookExpr, Precedence, Func) ->    {hook,HookExpr,Precedence,Func}.call(Name, Args, Prec, Hook) ->    {F,P} = func_prec(),    Item = {first,lexpr(Name, F, Hook),args(Args, Hook)},    maybe_paren(P, Prec, Item).fun_info(Extra) ->    leaf(format("% fun-info: ~w", [Extra])).%% BITS:bit_grp(Fs, Hook) ->    append([['<<'],            [try                 true = Fs =/= [],                 S = bin_string(Fs),                 true = io_lib:printable_list(S),                 {string,S}             catch _:_ ->                 bit_elems(Fs, Hook)            end],            ['>>']]).bin_string([]) ->    [];bin_string([{bin_element,_,{char,_,C},_,_}|Bin]) ->    [C | bin_string(Bin)].bit_elems(Es, Hook) ->    expr_list(Es, $,, fun bit_elem/2, Hook).bit_elem({bin_element,_,Expr,Sz,Types}, Hook) ->    P = max_prec(),    VChars = lexpr(Expr, P, Hook),    SChars = if                 Sz =/= default ->                     [VChars,$:,lexpr(Sz, P, Hook)];                 true ->                     VChars             end,    if        Types =/= default ->            [SChars,$/|bit_elem_types(Types)];        true ->	    SChars    end.bit_elem_types([T]) ->    [bit_elem_type(T)];bit_elem_types([T | Rest]) ->    [bit_elem_type(T), $-|bit_elem_types(Rest)].bit_elem_type({A,B}) ->    [lexpr(erl_parse:abstract(A), none),     $:,     lexpr(erl_parse:abstract(B), none)];bit_elem_type(T) ->    lexpr(erl_parse:abstract(T), none).%% end of BITSrecord_fields(Fs, Hook) ->    tuple(Fs, fun record_field/2, Hook).record_field({record_field,_,F,Val}, Hook) ->

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?