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 + -
显示快捷键?