1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(erl_pp).
21
22%%% Pretty printer for Erlang code in the same format as returned from
23%%% the parser. It does not always produce pretty code.
24
25-export([form/1,form/2,
26         attribute/1,attribute/2,function/1,function/2,
27         guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4]).
28
29-import(lists, [append/1,foldr/3,map/2,mapfoldl/3,reverse/1,reverse/2]).
30-import(io_lib, [write/1,format/2]).
31-import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0,
32                    type_inop_prec/1, type_preop_prec/1]).
33
34-define(DEFAULT_LINEWIDTH, 72).
35-define(DEFAULT_INDENT, 4).
36
37-type(hook_function() :: none
38                       | fun((Expr :: erl_parse:abstract_expr(),
39                              CurrentIndentation :: integer(),
40                              CurrentPrecedence :: non_neg_integer(),
41                              Options :: options()) ->
42                                   io_lib:chars())).
43
44-type(option() :: {hook, hook_function()}
45                | {encoding, latin1 | unicode | utf8}
46                | {quote_singleton_atom_types, boolean()}
47                | {linewidth, pos_integer()}
48                | {indent, pos_integer()}).
49-type(options() :: hook_function() | [option()]).
50
51-record(pp, {value_fun, singleton_atom_type_fun, string_fun, char_fun,
52	     linewidth=?DEFAULT_LINEWIDTH, indent=?DEFAULT_INDENT}).
53
54-record(options, {hook, encoding, opts}).
55
56%-define(DEBUG, true).
57
58-ifdef(DEBUG).
59-define(FORM_TEST(T),
60        _ = case T of
61                {eof, _Location} -> ok;
62                {warning, _W} -> ok;
63                {error, _E} -> ok;
64                _ -> ?TEST(T)
65            end).
66-define(EXPRS_TEST(L),
67        _ = [?TEST(E) || E <- L]).
68-define(TEST(T),
69        %% Assumes that erl_anno has been compiled with DEBUG=true.
70        %% erl_pp does not use the annoations, but test it anyway.
71        %% Note: hooks are not handled.
72        _ = try
73                erl_parse:map_anno(fun(A) when is_list(A) -> A end, T)
74            catch
75                _:_ ->
76                    erlang:error(badarg, [T])
77            end).
78-else.
79-define(FORM_TEST(T), ok).
80-define(EXPRS_TEST(T), ok).
81-define(TEST(T), ok).
82-endif.
83
84%%%
85%%% Exported functions
86%%%
87
88-spec(form(Form) -> io_lib:chars() when
89      Form :: erl_parse:abstract_form() | erl_parse:form_info()).
90
91form(Thing) ->
92    form(Thing, none).
93
94-spec(form(Form, Options) -> io_lib:chars() when
95      Form :: erl_parse:abstract_form() | erl_parse:form_info(),
96      Options :: options()).
97
98form(Thing, Options) ->
99    ?FORM_TEST(Thing),
100    State = state(Options),
101    frmt(lform(Thing, options(Options)), State).
102
103-spec(attribute(Attribute) -> io_lib:chars() when
104      Attribute :: erl_parse:abstract_form()).
105
106attribute(Thing) ->
107    attribute(Thing, none).
108
109-spec(attribute(Attribute, Options) -> io_lib:chars() when
110      Attribute :: erl_parse:abstract_form(),
111      Options :: options()).
112
113attribute(Thing, Options) ->
114    ?TEST(Thing),
115    State = state(Options),
116    frmt(lattribute(Thing, options(Options)), State).
117
118-spec(function(Function) -> io_lib:chars() when
119      Function :: erl_parse:abstract_form()).
120
121function(F) ->
122    function(F, none).
123
124-spec(function(Function, Options) -> io_lib:chars() when
125      Function :: erl_parse:abstract_form(),
126      Options :: options()).
127
128function(F, Options) ->
129    ?TEST(F),
130    frmt(lfunction(F, options(Options)), state(Options)).
131
132-spec(guard(Guard) -> io_lib:chars() when
133      Guard :: [erl_parse:abstract_expr()]).
134
135guard(Gs) ->
136    guard(Gs, none).
137
138-spec(guard(Guard, Options) -> io_lib:chars() when
139      Guard :: [erl_parse:abstract_expr()],
140      Options :: options()).
141
142guard(Gs, Options) ->
143    ?EXPRS_TEST(Gs),
144    frmt(lguard(Gs, options(Options)), state(Options)).
145
146-spec(exprs(Expressions) -> io_lib:chars() when
147      Expressions :: [erl_parse:abstract_expr()]).
148
149exprs(Es) ->
150    exprs(Es, 0, none).
151
152-spec(exprs(Expressions, Options) -> io_lib:chars() when
153      Expressions :: [erl_parse:abstract_expr()],
154      Options :: options()).
155
156exprs(Es, Options) ->
157    exprs(Es, 0, Options).
158
159-spec(exprs(Expressions, Indent, Options) -> io_lib:chars() when
160      Expressions :: [erl_parse:abstract_expr()],
161      Indent :: integer(),
162      Options :: options()).
163
164exprs(Es, I, Options) ->
165    ?EXPRS_TEST(Es),
166    frmt({seq,[],[],[$,],lexprs(Es, options(Options))}, I, state(Options)).
167
168-spec(expr(Expression) -> io_lib:chars() when
169      Expression :: erl_parse:abstract_expr()).
170
171expr(E) ->
172    ?TEST(E),
173    frmt(lexpr(E, 0, options(none)), state(none)).
174
175-spec(expr(Expression, Options) -> io_lib:chars() when
176      Expression :: erl_parse:abstract_expr(),
177      Options :: options()).
178
179expr(E, Options) ->
180    ?TEST(E),
181    frmt(lexpr(E, 0, options(Options)), state(Options)).
182
183-spec(expr(Expression, Indent, Options) -> io_lib:chars() when
184      Expression :: erl_parse:abstract_expr(),
185      Indent :: integer(),
186      Options :: options()).
187
188expr(E, I, Options) ->
189    ?TEST(E),
190    frmt(lexpr(E, 0, options(Options)), I, state(Options)).
191
192-spec(expr(Expression, Indent, Precedence, Options) -> io_lib:chars() when
193      Expression :: erl_parse:abstract_expr(),
194      Indent :: integer(),
195      Precedence :: non_neg_integer(),
196      Options :: options()).
197
198expr(E, I, P, Options) ->
199    ?TEST(E),
200    frmt(lexpr(E, P, options(Options)), I, state(Options)).
201
202%%%
203%%% Local functions
204%%%
205
206options(Options) when is_list(Options) ->
207    Hook = proplists:get_value(hook, Options, none),
208    Encoding = encoding(Options),
209    #options{hook = Hook, encoding = Encoding, opts = Options};
210options(Hook) ->
211    #options{hook = Hook, encoding = encoding([]), opts = Hook}.
212
213state(Options) when is_list(Options) ->
214    Quote = proplists:get_bool(quote_singleton_atom_types, Options),
215    State =
216	case encoding(Options) of
217	    latin1 -> latin1_state(Quote);
218	    unicode -> unicode_state(Quote)
219	end,
220    Indent = proplists:get_value(indent, Options, ?DEFAULT_INDENT),
221    LineWidth = proplists:get_value(linewidth, Options, ?DEFAULT_LINEWIDTH),
222    State#pp{indent=Indent, linewidth=LineWidth};
223state(_Hook) ->
224    latin1_state(false).
225
226latin1_state(Quote) ->
227    Options = [{encoding,latin1}],
228    ValueFun = fun(V) -> io_lib_pretty:print(V, Options) end,
229    SingletonFun =
230        case Quote of
231            true ->
232                fun(A) ->
233                        io_lib:write_string_as_latin1(atom_to_list(A), $')
234                end; %'
235            false ->
236                ValueFun
237        end,
238    #pp{value_fun  = ValueFun,
239        singleton_atom_type_fun = SingletonFun,
240        string_fun = fun io_lib:write_string_as_latin1/1,
241        char_fun   = fun io_lib:write_char_as_latin1/1}.
242
243unicode_state(Quote) ->
244    Options = [{encoding,unicode}],
245    ValueFun = fun(V) -> io_lib_pretty:print(V, Options) end,
246    SingletonFun =
247        case Quote of
248            true ->
249                fun(A) -> io_lib:write_string(atom_to_list(A), $') end; %'
250            false ->
251                ValueFun
252        end,
253    #pp{value_fun = ValueFun,
254        singleton_atom_type_fun = SingletonFun,
255        string_fun = fun io_lib:write_string/1,
256        char_fun   = fun io_lib:write_char/1}.
257
258encoding(Options) ->
259    case proplists:get_value(encoding, Options, epp:default_encoding()) of
260        latin1 -> latin1;
261        utf8 -> unicode;
262        unicode -> unicode
263    end.
264
265lform({attribute,Anno,Name,Arg}, Opts) ->
266    lattribute({attribute,Anno,Name,Arg}, Opts);
267lform({function,Anno,Name,Arity,Clauses}, Opts) ->
268    lfunction({function,Anno,Name,Arity,Clauses}, Opts);
269%% These are specials to make it easier for the compiler.
270lform({error,_}=E, Opts) ->
271    message(E, Opts);
272lform({warning,_}=W, Opts) ->
273    message(W, Opts);
274lform({eof,_Location}, _Opts) ->
275    $\n.
276
277message(M, #options{encoding = Encoding}) ->
278    F = case Encoding of
279            latin1 -> "~p\n";
280            unicode -> "~tp\n"
281        end,
282    leaf(format(F, [M])).
283
284lattribute({attribute,_Anno,type,Type}, Opts) ->
285    [typeattr(type, Type, Opts),leaf(".\n")];
286lattribute({attribute,_Anno,opaque,Type}, Opts) ->
287    [typeattr(opaque, Type, Opts),leaf(".\n")];
288lattribute({attribute,_Anno,spec,Arg}, _Opts) ->
289    [specattr(spec, Arg),leaf(".\n")];
290lattribute({attribute,_Anno,callback,Arg}, _Opts) ->
291    [specattr(callback, Arg),leaf(".\n")];
292lattribute({attribute,_Anno,Name,Arg}, Opts) ->
293    [lattribute(Name, Arg, Opts),leaf(".\n")].
294
295lattribute(module, {M,Vs}, _Opts) ->
296    A = a0(),
297    attr(module,[{var,A,pname(M)},
298                 foldr(fun(V, C) -> {cons,A,{var,A,V},C}
299                       end, {nil,A}, Vs)]);
300lattribute(module, M, _Opts) ->
301    attr(module, [{var,a0(),pname(M)}]);
302lattribute(export, Falist, _Opts) ->
303    attrib(export, falist(Falist));
304lattribute(import, Name, _Opts) when is_list(Name) ->
305    attr(import, [{var,a0(),pname(Name)}]);
306lattribute(import, {From,Falist}, _Opts) ->
307    attrib(import, [leaf(pname(From)),falist(Falist)]);
308lattribute(export_type, Talist, _Opts) ->
309    attrib(export_type, falist(Talist));
310lattribute(optional_callbacks, Falist, Opts) ->
311    try attrib(optional_callbacks, falist(Falist))
312    catch _:_ -> attr(optional_callbacks, [abstract(Falist, Opts)])
313    end;
314lattribute(file, {Name,Anno}, _Opts) ->
315    attr(file, [{string,a0(),Name},{integer,a0(),Anno}]);
316lattribute(record, {Name,Is}, Opts) ->
317    Nl = [leaf("-record("),{atom,Name},$,],
318    [{first,Nl,record_fields(Is, Opts)},$)];
319lattribute(Name, Arg, Options) ->
320    attr(Name, [abstract(Arg, Options)]).
321
322abstract(Arg, #options{encoding = Encoding}) ->
323    erl_parse:abstract(Arg, [{encoding,Encoding}]).
324
325typeattr(Tag, {TypeName,Type,Args}, _Opts) ->
326    {first,leaf("-"++atom_to_list(Tag)++" "),
327     typed(call({atom,a0(),TypeName}, Args, 0, options(none)), Type)}.
328
329ltype(T) ->
330    ltype(T, 0).
331
332ltype({ann_type,_Anno,[V,T]}, Prec) ->
333    {L,P,R} = type_inop_prec('::'),
334    Vl = ltype(V, L),
335    Tr = ltype(T, R),
336    El = {list,[{cstep,[Vl,' ::'],Tr}]},
337    maybe_paren(P, Prec, El);
338ltype({paren_type,_Anno,[T]}, P) ->
339    %% Generated before Erlang/OTP 18.
340    ltype(T, P);
341ltype({type,_Anno,union,Ts}, Prec) ->
342    {_L,P,R} = type_inop_prec('|'),
343    E = {seq,[],[],[' |'],ltypes(Ts, R)},
344    maybe_paren(P, Prec, E);
345ltype({type,_Anno,list,[T]}, _) ->
346    {seq,$[,$],$,,[ltype(T)]};
347ltype({type,_Anno,nonempty_list,[T]}, _) ->
348    {seq,$[,$],[$,],[ltype(T),leaf("...")]};
349ltype({type,Anno,nil,[]}, _) ->
350    lexpr({nil,Anno}, options(none));
351ltype({type,Anno,map,any}, _) ->
352    simple_type({atom,Anno,map}, []);
353ltype({type,_Anno,map,Pairs}, Prec) ->
354    {P,_R} = type_preop_prec('#'),
355    E = map_type(Pairs),
356    maybe_paren(P, Prec, E);
357ltype({type,Anno,tuple,any}, _) ->
358    simple_type({atom,Anno,tuple}, []);
359ltype({type,_Anno,tuple,Ts}, _) ->
360    tuple_type(Ts, fun ltype/2);
361ltype({type,_Anno,record,[{atom,_,N}|Fs]}, Prec) ->
362    {P,_R} = type_preop_prec('#'),
363    E = record_type(N, Fs),
364    maybe_paren(P, Prec, E);
365ltype({type,_Anno,range,[_I1,_I2]=Es}, Prec) ->
366    {_L,P,R} = type_inop_prec('..'),
367    F = fun(E, Opts) -> lexpr(E, R, Opts) end,
368    E = expr_list(Es, '..', F, options(none)),
369    maybe_paren(P, Prec, E);
370ltype({type,_Anno,binary,[I1,I2]}, _) ->
371    binary_type(I1, I2); % except binary()
372ltype({type,_Anno,'fun',[]}, _) ->
373    leaf("fun()");
374ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) ->
375    [fun_type(['fun',$(], FunType),$)];
376ltype({type,_Anno,'fun',[{type,_,product,_},_]}=FunType, _) ->
377    [fun_type(['fun',$(], FunType),$)];
378ltype({type,Anno,T,Ts}, _) ->
379    simple_type({atom,Anno,T}, Ts);
380ltype({user_type,Anno,T,Ts}, _) ->
381    simple_type({atom,Anno,T}, Ts);
382ltype({remote_type,Anno,[M,F,Ts]}, _) ->
383    simple_type({remote,Anno,M,F}, Ts);
384ltype({atom,_,T}, _) ->
385    {singleton_atom_type,T};
386ltype(E, P) ->
387    lexpr(E, P, options(none)).
388
389binary_type(I1, I2) ->
390    B = [[] || {integer,_,0} <- [I1]] =:= [],
391    U = [[] || {integer,_,0} <- [I2]] =:= [],
392    P = max_prec(),
393    E1 = [[leaf("_:"),lexpr(I1, P, options(none))] || B],
394    E2 = [[leaf("_:_*"),lexpr(I2, P, options(none))] || U],
395    case E1++E2 of
396        [] ->
397            leaf("<<>>");
398        Es ->
399            {seq,'<<','>>',[$,],Es}
400    end.
401
402map_type(Fs) ->
403    {first,[$#],map_pair_types(Fs)}.
404
405map_pair_types(Fs) ->
406    tuple_type(Fs, fun map_pair_type/2).
407
408map_pair_type({type,_Anno,map_field_assoc,[KType,VType]}, Prec) ->
409    {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]};
410map_pair_type({type,_Anno,map_field_exact,[KType,VType]}, Prec) ->
411    {list,[{cstep,[ltype(KType, Prec),leaf(" :=")],ltype(VType, Prec)}]}.
412
413record_type(Name, Fields) ->
414    {first,[record_name(Name)],field_types(Fields)}.
415
416field_types(Fs) ->
417    tuple_type(Fs, fun field_type/2).
418
419field_type({type,_Anno,field_type,[Name,Type]}, _Prec) ->
420    typed(lexpr(Name, options(none)), Type).
421
422typed(B, Type) ->
423    {list,[{cstep,[B,' ::'],ltype(Type)}]}.
424
425tuple_type([], _) ->
426    leaf("{}");
427tuple_type(Ts, F) ->
428    {seq,${,$},[$,],ltypes(Ts, F, 0)}.
429
430specattr(SpecKind, {FuncSpec,TypeSpecs}) ->
431    Func = case FuncSpec of
432               {F,_A} ->
433                   {atom,F};
434               {M,F,_A} ->
435                   [{atom,M},$:,{atom,F}]
436           end,
437    {first,leaf(lists:concat(["-", SpecKind, " "])),
438     {list,[{first,Func,spec_clauses(TypeSpecs)}]}}.
439
440spec_clauses(TypeSpecs) ->
441    {prefer_nl,[$;],[sig_type(T) || T <- TypeSpecs]}.
442
443sig_type({type,_Anno,bounded_fun,[T,Gs]}) ->
444    guard_type(fun_type([], T), Gs);
445sig_type(FunType) ->
446    fun_type([], FunType).
447
448guard_type(Before, Gs) ->
449    Opts = options(none),
450    Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, Opts)}]},
451    {list,[{step,Before,Gl}]}.
452
453constraint({type,_Anno,constraint,[{atom,_,is_subtype},[{var,_,_}=V,Type]]},
454           _Opts) ->
455    typed(lexpr(V, options(none)), Type);
456constraint({type,_Anno,constraint,[Tag,As]}, _Opts) ->
457    simple_type(Tag, As).
458
459fun_type(Before, {type,_,'fun',[FType,Ret]}) ->
460    {first,Before,{step,[type_args(FType),' ->'],ltype(Ret)}}.
461
462type_args({type,_Anno,any}) ->
463    leaf("(...)");
464type_args({type,_line,product,Ts}) ->
465    targs(Ts).
466
467simple_type(Tag, Types) ->
468    {first,lexpr(Tag, options(none)),targs(Types)}.
469
470targs(Ts) ->
471    {seq,$(,$),[$,],ltypes(Ts, 0)}.
472
473ltypes(Ts, Prec) ->
474    ltypes(Ts, fun ltype/2, Prec).
475
476ltypes(Ts, F, Prec) ->
477    [F(T, Prec) || T <- Ts].
478
479attr(Name, Args) ->
480    {first,[$-,{atom,Name}],args(Args, options(none))}.
481
482attrib(Name, Args) ->
483    {first,[$-,{atom,Name}],[{seq,$(,$),[$,],Args}]}.
484
485pname(['' | As]) ->
486    [$. | pname(As)];
487pname([A]) ->
488    write(A);
489pname([A | As]) ->
490    [write(A),$.|pname(As)];
491pname(A) when is_atom(A) ->
492    write(A).
493
494falist([]) ->
495    ['[]'];
496falist(Falist) ->
497    L = [begin
498             {Name,Arity} = Fa,
499             [{atom,Name},leaf(format("/~w", [Arity]))]
500         end || Fa <- Falist],
501    [{seq,$[,$],$,,L}].
502
503lfunction({function,_Anno,Name,_Arity,Cs}, Opts) ->
504    Cll = nl_clauses(fun (C, H) -> func_clause(Name, C, H) end, $;, Opts, Cs),
505    [Cll,leaf(".\n")].
506
507func_clause(Name, {clause,Anno,Head,Guard,Body}, Opts) ->
508    Hl = call({atom,Anno,Name}, Head, 0, Opts),
509    Gl = guard_when(Hl, Guard, Opts),
510    Bl = body(Body, Opts),
511    {step,Gl,Bl}.
512
513guard_when(Before, Guard, Opts) ->
514    guard_when(Before, Guard, Opts, ' ->').
515
516guard_when(Before, Guard, Opts, After) ->
517    Gl = lguard(Guard, Opts),
518    [{list,[{step,Before,Gl}]},After].
519
520lguard([E|Es], Opts) when is_list(E) ->
521    {list,[{step,'when',expr_list([E|Es], [$;], fun guard0/2, Opts)}]};
522lguard([E|Es], Opts) -> % before R6
523    lguard([[E|Es]], Opts);
524lguard([], _) ->
525    [].
526
527guard0(Es, Opts) ->
528    expr_list(Es, [$,], fun lexpr/2, Opts).
529
530%% body(Before, Es, Opts) -> [Char].
531
532body([E], Opts) ->
533    lexpr(E, Opts);
534body(Es, Opts) ->
535    {prefer_nl,[$,],lexprs(Es, Opts)}.
536
537lexpr(E, Opts) ->
538    lexpr(E, 0, Opts).
539
540lexpr({var,_,V}, _, _) when is_integer(V) ->    %Special hack for Robert
541    leaf(format("_~w", [V]));
542lexpr({var,_,V}, _, _) -> leaf(format("~ts", [V]));
543lexpr({char,_,C}, _, _) -> {char,C};
544lexpr({integer,_,N}, _, _) -> leaf(write(N));
545lexpr({float,_,F}, _, _) -> leaf(write(F));
546lexpr({atom,_,A}, _, _) -> {atom,A};
547lexpr({string,_,S}, _, _) -> {string,S};
548lexpr({nil,_}, _, _) -> '[]';
549lexpr({cons,_,H,T}, _, Opts) ->
550    list(T, [H], Opts);
551lexpr({lc,_,E,Qs}, _Prec, Opts) ->
552    Lcl = {list,[{step,[lexpr(E, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
553    {list,[{seq,$[,[],[[]],[{force_nl,leaf(" "),[Lcl]}]},$]]};
554    %% {list,[{step,$[,Lcl},$]]};
555lexpr({bc,_,E,Qs}, _Prec, Opts) ->
556    P = max_prec(),
557    Lcl = {list,[{step,[lexpr(E, P, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
558    {list,[{seq,'<<',[],[[]],[{force_nl,leaf(" "),[Lcl]}]},'>>']};
559    %% {list,[{step,'<<',Lcl},'>>']};
560lexpr({tuple,_,Elts}, _, Opts) ->
561    tuple(Elts, Opts);
562lexpr({record_index, _, Name, F}, Prec, Opts) ->
563    {P,R} = preop_prec('#'),
564    Nl = record_name(Name),
565    El = [Nl,$.,lexpr(F, R, Opts)],
566    maybe_paren(P, Prec, El);
567lexpr({record, _, Name, Fs}, Prec, Opts) ->
568    {P,_R} = preop_prec('#'),
569    Nl = record_name(Name),
570    El = {first,Nl,record_fields(Fs, Opts)},
571    maybe_paren(P, Prec, El);
572lexpr({record_field, _, Rec, Name, F}, Prec, Opts) ->
573    {L,P,R} = inop_prec('#'),
574    Rl = lexpr(Rec, L, Opts),
575    Sep = hash_after_integer(Rec, [$#]),
576    Nl = [Sep,{atom,Name},$.],
577    El = [Rl,Nl,lexpr(F, R, Opts)],
578    maybe_paren(P, Prec, El);
579lexpr({record, _, Rec, Name, Fs}, Prec, Opts) ->
580    {L,P,_R} = inop_prec('#'),
581    Rl = lexpr(Rec, L, Opts),
582    Sep = hash_after_integer(Rec, []),
583    Nl = record_name(Name),
584    El = {first,[Rl,Sep,Nl],record_fields(Fs, Opts)},
585    maybe_paren(P, Prec, El);
586lexpr({record_field, _, {atom,_,''}, F}, Prec, Opts) ->
587    {_L,P,R} = inop_prec('.'),
588    El = [$.,lexpr(F, R, Opts)],
589    maybe_paren(P, Prec, El);
590lexpr({record_field, _, Rec, F}, Prec, Opts) ->
591    {L,P,R} = inop_prec('.'),
592    El = [lexpr(Rec, L, Opts),$.,lexpr(F, R, Opts)],
593    maybe_paren(P, Prec, El);
594lexpr({map, _, Fs}, Prec, Opts) ->
595    {P,_R} = preop_prec('#'),
596    El = {first,$#,map_fields(Fs, Opts)},
597    maybe_paren(P, Prec, El);
598lexpr({map, _, Map, Fs}, Prec, Opts) ->
599    {L,P,_R} = inop_prec('#'),
600    Rl = lexpr(Map, L, Opts),
601    Sep = hash_after_integer(Map, [$#]),
602    El = {first,[Rl|Sep],map_fields(Fs, Opts)},
603    maybe_paren(P, Prec, El);
604lexpr({block,_,Es}, _, Opts) ->
605    {list,[{step,'begin',body(Es, Opts)},{reserved,'end'}]};
606lexpr({'if',_,Cs}, _, Opts) ->
607    {list,[{step,'if',if_clauses(Cs, Opts)},{reserved,'end'}]};
608lexpr({'case',_,Expr,Cs}, _, Opts) ->
609    {list,[{step,{list,[{step,'case',lexpr(Expr, Opts)},{reserved,'of'}]},
610            cr_clauses(Cs, Opts)},
611           {reserved,'end'}]};
612lexpr({'cond',_,Cs}, _, Opts) ->
613    {list,[{step,leaf("cond"),cond_clauses(Cs, Opts)},{reserved,'end'}]};
614lexpr({'receive',_,Cs}, _, Opts) ->
615    {list,[{step,'receive',cr_clauses(Cs, Opts)},{reserved,'end'}]};
616lexpr({'receive',_,Cs,To,ToOpt}, _, Opts) ->
617    Al = {list,[{step,[lexpr(To, Opts),' ->'],body(ToOpt, Opts)}]},
618    {list,[{step,'receive',cr_clauses(Cs, Opts)},
619           {step,'after',Al},
620           {reserved,'end'}]};
621lexpr({'fun',_,{function,F,A}}, _Prec, _Opts) ->
622    [leaf("fun "),{atom,F},leaf(format("/~w", [A]))];
623lexpr({'fun',A,{function,_,_}=Func,Extra}, Prec, Opts) ->
624    {force_nl,fun_info(Extra),lexpr({'fun',A,Func}, Prec, Opts)};
625lexpr({'fun',_,{function,M,F,A}}, _Prec, Opts) ->
626    NameItem = lexpr(M, Opts),
627    CallItem = lexpr(F, Opts),
628    ArityItem = lexpr(A, Opts),
629    ["fun ",NameItem,$:,CallItem,$/,ArityItem];
630lexpr({'fun',_,{clauses,Cs}}, _Prec, Opts) ->
631    {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]};
632lexpr({named_fun,_,Name,Cs}, _Prec, Opts) ->
633    {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
634           {reserved,'end'}]};
635lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
636    {force_nl,fun_info(Extra),
637     {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]}};
638lexpr({named_fun,_,Name,Cs,Extra}, _Prec, Opts) ->
639    {force_nl,fun_info(Extra),
640     {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
641            {reserved,'end'}]}};
642lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
643    case erl_internal:bif(M, F, length(Args)) of
644        true when F =/= float ->
645            call(N, Args, Prec, Opts);
646        true ->
647            call(Name, Args, Prec, Opts);
648        false ->
649            call(Name, Args, Prec, Opts)
650    end;
651lexpr({call,_,Name,Args}, Prec, Opts) ->
652    call(Name, Args, Prec, Opts);
653lexpr({'try',_,Es,Scs,Ccs,As}, _, Opts) ->
654    {list,[if
655               Scs =:= [] ->
656                   {step,'try',body(Es, Opts)};
657               true ->
658                   {step,{list,[{step,'try',body(Es, Opts)},{reserved,'of'}]},
659                    cr_clauses(Scs, Opts)}
660           end] ++
661           if
662               Ccs =:= [] ->
663                   [];
664               true ->
665                   [{step,'catch',try_clauses(Ccs, Opts)}]
666           end ++
667           if
668               As =:= [] ->
669                   [];
670               true ->
671                   [{step,'after',body(As, Opts)}]
672           end ++
673           [{reserved,'end'}]};
674lexpr({'catch',_,Expr}, Prec, Opts) ->
675    {P,R} = preop_prec('catch'),
676    El = {list,[{step,'catch',lexpr(Expr, R, Opts)}]},
677    maybe_paren(P, Prec, El);
678lexpr({match,_,Lhs,Rhs}, Prec, Opts) ->
679    {L,P,R} = inop_prec('='),
680    Pl = lexpr(Lhs, L, Opts),
681    Rl = lexpr(Rhs, R, Opts),
682    El = {list,[{cstep,[Pl,' ='],Rl}]},
683    maybe_paren(P, Prec, El);
684lexpr({op,_,Op,Arg}, Prec, Opts) ->
685    {P,R} = preop_prec(Op),
686    Ol = {reserved, leaf(format("~s ", [Op]))},
687    El = [Ol,lexpr(Arg, R, Opts)],
688    maybe_paren(P, Prec, El);
689lexpr({op,_,Op,Larg,Rarg}, Prec, Opts)  when Op =:= 'orelse';
690                                             Op =:= 'andalso' ->
691    %% Breaks lines since R12B.
692    {L,P,R} = inop_prec(Op),
693    Ll = lexpr(Larg, L, Opts),
694    Ol = {reserved, leaf(format("~s", [Op]))},
695    Lr = lexpr(Rarg, R, Opts),
696    El = {prefer_nl,[[]],[Ll,Ol,Lr]},
697    maybe_paren(P, Prec, El);
698lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) ->
699    {L,P,R} = inop_prec(Op),
700    Ll = lexpr(Larg, L, Opts),
701    Ol = {reserved, leaf(format("~s", [Op]))},
702    Lr = lexpr(Rarg, R, Opts),
703    El = {list,[Ll,Ol,Lr]},
704    maybe_paren(P, Prec, El);
705%% Special expressions which are not really legal everywhere.
706lexpr({remote,_,M,F}, Prec, Opts) ->
707    {L,P,R} = inop_prec(':'),
708    NameItem = lexpr(M, L, Opts),
709    CallItem = lexpr(F, R, Opts),
710    maybe_paren(P, Prec, [NameItem,$:,CallItem]);
711%% BIT SYNTAX:
712lexpr({bin,_,Fs}, _, Opts) ->
713    bit_grp(Fs, Opts);
714%% Special case for straight values.
715lexpr({value,_,Val}, _,_) ->
716    {value,Val};
717%% Now do the hook.
718lexpr(Other, _Precedence, #options{hook = none}) ->
719    leaf(format("INVALID-FORM:~w:",[Other]));
720lexpr(HookExpr, Precedence, #options{hook = {Mod,Func,Eas}})
721                                        when Mod =/= 'fun' ->
722    {ehook,HookExpr,Precedence,{Mod,Func,Eas}};
723lexpr(HookExpr, Precedence, #options{hook = Func, opts = Options}) ->
724    {hook,HookExpr,Precedence,Func,Options}.
725
726%% An integer is separated from the following '#' by a space, which
727%% erl_scan can handle.
728hash_after_integer({integer, _, _}, C) ->
729    [$\s|C];
730hash_after_integer({'fun',_,{function, _, _}}, C) ->
731    [$\s|C];
732hash_after_integer({'fun',_,{function, _, _, _}}, C) ->
733    [$\s|C];
734hash_after_integer(_, C) ->
735    C.
736
737call(Name, Args, Prec, Opts) ->
738    {F,P} = func_prec(),
739    Item = {first,lexpr(Name, F, Opts),args(Args, Opts)},
740    maybe_paren(P, Prec, Item).
741
742fun_info(Extra) ->
743    [leaf("% fun-info: "),{value,Extra}].
744
745%% BITS:
746
747bit_grp([], _Opts) ->
748    leaf("<<>>");
749bit_grp(Fs, Opts) ->
750    append([['<<'], [bit_elems(Fs, Opts)], ['>>']]).
751
752bit_elems(Es, Opts) ->
753    expr_list(Es, $,, fun bit_elem/2, Opts).
754
755bit_elem({bin_element,_,Expr,Sz,Types}, Opts) ->
756    P = max_prec(),
757    VChars = lexpr(Expr, P, Opts),
758    SChars = if
759                 Sz =/= default ->
760                     [VChars,$:,lexpr(Sz, P, Opts)];
761                 true ->
762                     VChars
763             end,
764    if
765        Types =/= default ->
766            [SChars,$/|bit_elem_types(Types)];
767        true ->
768            SChars
769    end.
770
771bit_elem_types([T]) ->
772    [bit_elem_type(T)];
773bit_elem_types([T | Rest]) ->
774    [bit_elem_type(T), $-|bit_elem_types(Rest)].
775
776bit_elem_type({A,B}) ->
777    [lexpr(erl_parse:abstract(A), options(none)),
778     $:,
779     lexpr(erl_parse:abstract(B), options(none))];
780bit_elem_type(T) ->
781    lexpr(erl_parse:abstract(T), options(none)).
782
783%% end of BITS
784
785record_name(Name) ->
786    [$#,{atom,Name}].
787
788record_fields(Fs, Opts) ->
789    tuple(Fs, fun record_field/2, Opts).
790
791record_field({record_field,_,F,Val}, Opts) ->
792    {L,_P,R} = inop_prec('='),
793    Fl = lexpr(F, L, Opts),
794    Vl = lexpr(Val, R, Opts),
795    {list,[{cstep,[Fl,' ='],Vl}]};
796record_field({typed_record_field,{record_field,_,F,Val},Type}, Opts) ->
797    {L,_P,R} = inop_prec('='),
798    Fl = lexpr(F, L, Opts),
799    Vl = typed(lexpr(Val, R, Opts), Type),
800    {list,[{cstep,[Fl,' ='],Vl}]};
801record_field({typed_record_field,Field,Type}, Opts) ->
802    typed(record_field(Field, Opts), Type);
803record_field({record_field,_,F}, Opts) ->
804    lexpr(F, 0, Opts).
805
806map_fields(Fs, Opts) ->
807    tuple(Fs, fun map_field/2, Opts).
808
809map_field({map_field_assoc,_,K,V}, Opts) ->
810    Pl = lexpr(K, 0, Opts),
811    {list,[{step,[Pl,leaf(" =>")],lexpr(V, 0, Opts)}]};
812map_field({map_field_exact,_,K,V}, Opts) ->
813    Pl = lexpr(K, 0, Opts),
814    {list,[{step,[Pl,leaf(" :=")],lexpr(V, 0, Opts)}]}.
815
816list({cons,_,H,T}, Es, Opts) ->
817    list(T, [H|Es], Opts);
818list({nil,_}, Es, Opts) ->
819    proper_list(reverse(Es), Opts);
820list(Other, Es, Opts) ->
821    improper_list(reverse(Es, [Other]), Opts).
822
823%% if_clauses(Clauses, Opts) -> [Char].
824%%  Print 'if' clauses.
825
826if_clauses(Cs, Opts) ->
827    clauses(fun if_clause/2, Opts, Cs).
828
829if_clause({clause,_,[],G,B}, Opts) ->
830    Gl = [guard_no_when(G, Opts),' ->'],
831    {step,Gl,body(B, Opts)}.
832
833guard_no_when([E|Es], Opts) when is_list(E) ->
834    expr_list([E|Es], $;, fun guard0/2, Opts);
835guard_no_when([E|Es], Opts) -> % before R6
836    guard_no_when([[E|Es]], Opts);
837guard_no_when([], _) -> % cannot happen
838    leaf("true").
839
840%% cr_clauses(Clauses, Opts) -> [Char].
841%%  Print 'case'/'receive' clauses.
842
843cr_clauses(Cs, Opts) ->
844    clauses(fun cr_clause/2, Opts, Cs).
845
846cr_clause({clause,_,[T],G,B}, Opts) ->
847    El = lexpr(T, 0, Opts),
848    Gl = guard_when(El, G, Opts),
849    Bl = body(B, Opts),
850    {step,Gl,Bl}.
851
852%% try_clauses(Clauses, Opts) -> [Char].
853%%  Print 'try' clauses.
854
855try_clauses(Cs, Opts) ->
856    clauses(fun try_clause/2, Opts, Cs).
857
858try_clause({clause,_,[{tuple,_,[C,V,S]}],G,B}, Opts) ->
859    Cs = lexpr(C, 0, Opts),
860    El = lexpr(V, 0, Opts),
861    CsEl = [Cs,$:,El],
862    Sl = stack_backtrace(S, CsEl, Opts),
863    Gl = guard_when(Sl, G, Opts),
864    Bl = body(B, Opts),
865    {step,Gl,Bl}.
866
867stack_backtrace({var,_,'_'}, El, _Opts) ->
868    El;
869stack_backtrace(S, El, Opts) ->
870    El++[$:,lexpr(S, 0, Opts)].
871
872%% fun_clauses(Clauses, Opts) -> [Char].
873%%  Print 'fun' clauses.
874
875fun_clauses(Cs, Opts, unnamed) ->
876    nl_clauses(fun fun_clause/2, [$;], Opts, Cs);
877fun_clauses(Cs, Opts, {named, Name}) ->
878    nl_clauses(fun (C, H) ->
879                       {step,Gl,Bl} = fun_clause(C, H),
880                       {step,[atom_to_list(Name),Gl],Bl}
881               end, [$;], Opts, Cs).
882
883fun_clause({clause,_,A,G,B}, Opts) ->
884    El = args(A, Opts),
885    Gl = guard_when(El, G, Opts),
886    Bl = body(B, Opts),
887    {step,Gl,Bl}.
888
889%% cond_clauses(Clauses, Opts) -> [Char].
890%%  Print 'cond' clauses.
891
892cond_clauses(Cs, Opts) ->
893    clauses(fun cond_clause/2, Opts, Cs).
894
895cond_clause({clause,_,[],[[E]],B}, Opts) ->
896    {step,[lexpr(E, Opts),' ->'],body(B, Opts)}.
897
898%% nl_clauses(Type, Opts, Clauses) -> [Char].
899%%  Generic clause printing function (always breaks lines).
900
901nl_clauses(Type, Sep, Opts, Cs) ->
902    {prefer_nl,Sep,lexprs(Cs, Type, Opts)}.
903
904%% clauses(Type, Opts, Clauses) -> [Char].
905%%  Generic clause printing function (breaks lines since R12B).
906
907clauses(Type, Opts, Cs) ->
908    {prefer_nl,[$;],lexprs(Cs, Type, Opts)}.
909
910%% lc_quals(Qualifiers, After, Opts)
911%% List comprehension qualifiers (breaks lines since R12B).
912
913lc_quals(Qs, Opts) ->
914    {prefer_nl,[$,],lexprs(Qs, fun lc_qual/2, Opts)}.
915
916lc_qual({b_generate,_,Pat,E}, Opts) ->
917    Pl = lexpr(Pat, 0, Opts),
918    {list,[{step,[Pl,leaf(" <=")],lexpr(E, 0, Opts)}]};
919lc_qual({generate,_,Pat,E}, Opts) ->
920    Pl = lexpr(Pat, 0, Opts),
921    {list,[{step,[Pl,leaf(" <-")],lexpr(E, 0, Opts)}]};
922lc_qual(Q, Opts) ->
923    lexpr(Q, 0, Opts).
924
925proper_list(Es, Opts) ->
926    {seq,$[,$],[$,],lexprs(Es, Opts)}.
927
928improper_list(Es, Opts) ->
929    {seq,$[,$],[{$,,' |'}],lexprs(Es, Opts)}.
930
931tuple(L, Opts) ->
932    tuple(L, fun lexpr/2, Opts).
933
934tuple([], _F, _Opts) ->
935    leaf("{}");
936tuple(Es, F, Opts) ->
937    {seq,${,$},[$,],lexprs(Es, F, Opts)}.
938
939args(As, Opts) ->
940    {seq,$(,$),[$,],lexprs(As, Opts)}.
941
942expr_list(Es, Sep, F, Opts) ->
943    {seq,[],[],Sep,lexprs(Es, F, Opts)}.
944
945lexprs(Es, Opts) ->
946    lexprs(Es, fun lexpr/2, Opts).
947
948lexprs(Es, F, Opts) ->
949    [F(E, Opts) || E <- Es].
950
951maybe_paren(P, Prec, Expr) when P < Prec ->
952    [$(,Expr,$)];
953maybe_paren(_P, _Prec, Expr) ->
954    Expr.
955
956leaf(S) ->
957    {leaf,string:length(S),S}.
958
959%%% Do the formatting. Currently nothing fancy. Could probably have
960%%% done it in one single pass.
961
962frmt(Item, PP) ->
963    frmt(Item, 0, PP).
964
965frmt(Item, I, PP) ->
966    ST = spacetab(),
967    WT = wordtable(),
968    {Chars,_Length} = f(Item, I, ST, WT, PP),
969    [Chars].
970
971%%% What the tags mean:
972%%% - C: a character
973%%% - [I|Is]: Is follow after I without newline or space
974%%% - {list,IPs}: try to put all IPs on one line, if that fails newlines
975%%%   and indentation are inserted between IPs.
976%%% - {first,I,IP2}: IP2 follows after I, and is output with an indentation
977%%%   updated with the width of I.
978%%% - {seq,Before,After,Separator,IPs}: a sequence of Is separated by
979%%%   Separator. Before is output before IPs, and the indentation of IPs
980%%%   is updated with the width of Before. After follows after IPs.
981%%% - {force_nl,ExtraInfo,I}: fun-info (a comment) forces linebreak before I.
982%%% - {prefer_nl,Sep,IPs}: forces linebreak between Is unlesss negative
983%%%   indentation.
984%%% - {atom,A}: an atom
985%%% - {singleton_atom_type,A}: a singleton atom type
986%%% - {char,C}: a character
987%%% - {string,S}: a string.
988%%% - {value,T}: a term.
989%%% - {hook,...}, {ehook,...}: hook expressions.
990%%%
991%%% list, first, seq, force_nl, and prefer_nl all accept IPs, where each
992%%% element is either an item or a tuple {step|cstep,I1,I2}. step means
993%%% that I2 is output after linebreak and an incremented indentation.
994%%% cstep works similarly, but no linebreak if the width of I1 is less
995%%% than the indentation (this is for "A = <expression over several lines>).
996
997f([]=Nil, _I0, _ST, _WT, _PP) ->
998    {Nil,0};
999f(C, _I0, _ST, _WT, _PP) when is_integer(C) ->
1000    {C,1};
1001f({leaf,Length,Chars}, _I0, _ST, _WT, _PP) ->
1002    {Chars,Length};
1003f([Item|Items], I0, ST, WT, PP) ->
1004    consecutive(Items, f(Item, I0, ST, WT, PP), I0, ST, WT, PP);
1005f({list,Items}, I0, ST, WT, PP) ->
1006    f({seq,[],[],[[]],Items}, I0, ST, WT, PP);
1007f({first,E,Item}, I0, ST, WT, PP) ->
1008    f({seq,E,[],[[]],[Item]}, I0, ST, WT, PP);
1009f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) ->
1010    BCharsSize = f(Before, I0, ST, WT, PP),
1011    I = indent(BCharsSize, I0),
1012    CharsSizeL = fl(LItems, Sep, I, After, ST, WT, PP),
1013    {CharsL,SizeL} = unz(CharsSizeL),
1014    {BCharsL,BSizeL} = unz1([BCharsSize]),
1015    Sizes = BSizeL ++ SizeL,
1016    NSepChars = if
1017                    is_list(Sep), Sep =/= [] ->
1018                        erlang:max(0, length(CharsL)-1); % not string:length
1019                    true ->
1020                        0
1021                end,
1022    case same_line(I0, Sizes, NSepChars, PP) of
1023        {yes,Size} ->
1024            Chars = if
1025                        NSepChars > 0 -> insert_sep(CharsL, $\s);
1026                        true -> CharsL
1027                    end,
1028            {BCharsL++Chars,Size};
1029        no ->
1030            CharsList = handle_step(CharsSizeL, I, ST, PP),
1031            {LChars, LSize} =
1032                maybe_newlines(CharsList, LItems, I, NSepChars, ST, PP),
1033            {[BCharsL,LChars],nsz(LSize, I0)}
1034    end;
1035f({force_nl,_ExtraInfoItem,Item}, I, ST, WT, PP) when I < 0 ->
1036    %% Extra info is a comment; cannot have that on the same line
1037    f(Item, I, ST, WT, PP);
1038f({force_nl,ExtraInfoItem,Item}, I, ST, WT, PP) ->
1039    f({prefer_nl,[],[ExtraInfoItem,Item]}, I, ST, WT, PP);
1040f({prefer_nl,Sep,LItems}, I, ST, WT, PP) when I < 0 ->
1041    f({seq,[],[],Sep,LItems}, I, ST, WT, PP);
1042f({prefer_nl,Sep,LItems}, I0, ST, WT, PP) ->
1043    CharsSize2L = fl(LItems, Sep, I0, [], ST, WT, PP),
1044    {_CharsL,Sizes} = unz(CharsSize2L),
1045    if
1046        Sizes =:= [] ->
1047            {[], 0};
1048        true ->
1049            {insert_newlines(CharsSize2L, I0, ST, PP),
1050             nsz(lists:last(Sizes), I0)}
1051    end;
1052f({value,V}, I, ST, WT, PP) ->
1053    f(write_a_value(V, PP), I, ST, WT, PP);
1054f({atom,A}, I, ST, WT, PP) ->
1055    f(write_an_atom(A, PP), I, ST, WT, PP);
1056f({singleton_atom_type,A}, I, ST, WT, PP) ->
1057    f(write_a_singleton_atom_type(A, PP), I, ST, WT, PP);
1058f({char,C}, I, ST, WT, PP) ->
1059    f(write_a_char(C, PP), I, ST, WT, PP);
1060f({string,S}, I, ST, WT, PP) ->
1061    f(write_a_string(S, I, PP), I, ST, WT, PP);
1062f({reserved,R}, I, ST, WT, PP) ->
1063    f(R, I, ST, WT, PP);
1064f({hook,HookExpr,Precedence,Func,Options}, I, _ST, _WT, _PP) ->
1065    Chars = Func(HookExpr, I, Precedence, Options),
1066    {Chars,indentation(Chars, I)};
1067f({ehook,HookExpr,Precedence,{Mod,Func,Eas}=ModFuncEas}, I, _ST, _WT, _PP) ->
1068    Chars = apply(Mod, Func, [HookExpr,I,Precedence,ModFuncEas|Eas]),
1069    {Chars,indentation(Chars, I)};
1070f(WordName, _I, _ST, WT, _PP) when is_atom(WordName) ->
1071    word(WordName, WT).
1072
1073%% fl(ListItems, I0, ST, WT) -> [[CharsSize1,CharsSize2]]
1074%% ListItems = [{Item,Items}|Item]
1075fl([], _Sep, I0, After, ST, WT, PP) ->
1076    [[f(After, I0, ST, WT, PP),{[],0}]];
1077fl(CItems, Sep0, I0, After, ST, WT, PP) ->
1078    F = fun({step,Item1,Item2}, S) ->
1079                [f(Item1, I0, ST, WT, PP),
1080                 f([Item2,S], incr(I0, PP#pp.indent), ST, WT, PP)];
1081           ({cstep,Item1,Item2}, S) ->
1082                {_,Sz1} = CharSize1 = f(Item1, I0, ST, WT, PP),
1083                if
1084                    is_integer(Sz1), Sz1 < PP#pp.indent ->
1085                        Item2p = [leaf("\s"),Item2,S],
1086                        [consecutive(Item2p, CharSize1, I0, ST, WT, PP),{[],0}];
1087                    true ->
1088                        [CharSize1,f([Item2,S], incr(I0, PP#pp.indent), ST, WT, PP)]
1089                end;
1090           ({reserved,Word}, S) ->
1091                [f([Word,S], I0, ST, WT, PP),{[],0}];
1092           (Item, S) ->
1093                [f([Item,S], I0, ST, WT, PP),{[],0}]
1094        end,
1095    {Sep,LastSep} = sep(Sep0),
1096    fl1(CItems, F, Sep, LastSep, After).
1097
1098sep([{S,LS}]) -> {[S],[LS]};
1099sep({_,_}=Sep) -> Sep;
1100sep(S) -> {S, S}.
1101
1102fl1([CItem], F, _Sep, _LastSep, After) ->
1103    [F(CItem,After)];
1104fl1([CItem1,CItem2], F, _Sep, LastSep, After) ->
1105    [F(CItem1, LastSep),F(CItem2, After)];
1106fl1([CItem|CItems], F, Sep, LastSep, After) ->
1107    [F(CItem, Sep)|fl1(CItems, F, Sep, LastSep, After)].
1108
1109consecutive(Items, CharSize1, I0, ST, WT, PP) ->
1110    {CharsSizes,_Length} =
1111        mapfoldl(fun(Item, Len) ->
1112                         CharsSize = f(Item, Len, ST, WT, PP),
1113                         {CharsSize,indent(CharsSize, Len)}
1114                 end, indent(CharSize1, I0), Items),
1115    {CharsL,SizeL} = unz1([CharSize1|CharsSizes]),
1116    {CharsL,line_size(SizeL)}.
1117
1118unz(CharsSizesL) ->
1119    unz1(append(CharsSizesL)).
1120
1121unz1(CharSizes) ->
1122    lists:unzip(nonzero(CharSizes)).
1123
1124nonzero(CharSizes) ->
1125    lists:filter(fun({_,Sz}) -> Sz =/= 0 end, CharSizes).
1126
1127maybe_newlines([{Chars,Size}], [], _I, _NSepChars, _ST, _PP) ->
1128    {Chars,Size};
1129maybe_newlines(CharsSizeList, Items, I, NSepChars, ST, PP) when I >= 0 ->
1130    maybe_sep(CharsSizeList, Items, I, NSepChars, nl_indent(I, ST), PP).
1131
1132maybe_sep([{Chars1,Size1}|CharsSizeL], [Item|Items], I0, NSepChars, Sep, PP) ->
1133    I1 = case classify_item(Item) of
1134             atomic ->
1135                 I0 + Size1;
1136             _ ->
1137                 PP#pp.linewidth+1
1138         end,
1139    maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars, Size1, [Chars1], PP).
1140
1141maybe_sep1([{Chars,Size}|CharsSizeL], [Item|Items],
1142           I0, I, Sep, NSepChars, Sz0, A, PP) ->
1143    case classify_item(Item) of
1144        atomic when is_integer(Size) ->
1145            Size1 = Size + 1,
1146            I1 = I + Size1,
1147            if
1148                I1 =< PP#pp.linewidth ->
1149                    A1 = if
1150                             NSepChars > 0 -> [Chars,$\s|A];
1151                             true -> [Chars|A]
1152                         end,
1153                    maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars,
1154                               Sz0 + Size1, A1, PP);
1155                true ->
1156                    A1 = [Chars,Sep|A],
1157                    maybe_sep1(CharsSizeL, Items, I0, I0 + Size, Sep,
1158                               NSepChars, Size1, A1, PP)
1159            end;
1160        _ ->
1161            A1 = [Chars,Sep|A],
1162            maybe_sep1(CharsSizeL, Items, I0, PP#pp.linewidth+1, Sep, NSepChars,
1163                       0, A1, PP)
1164    end;
1165maybe_sep1(_CharsSizeL, _Items, _Io, _I, _Sep, _NSepChars, Sz, A, _PP) ->
1166    {lists:reverse(A), Sz}.
1167
1168insert_newlines(CharsSizesL, I, ST, PP) when I >= 0 ->
1169    {CharsL, _} = unz1(handle_step(CharsSizesL, I, ST, PP)),
1170    insert_nl(CharsL, I, ST).
1171
1172handle_step(CharsSizesL, I, ST, PP) ->
1173    map(fun([{_C1,0},{_C2,0}]) ->
1174                {[], 0};
1175           ([{C1,Sz1},{_C2,0}]) ->
1176                {C1, Sz1};
1177           ([{C1,Sz1},{C2,Sz2}]) when Sz2 > 0 ->
1178                {insert_nl([C1,C2], I+PP#pp.indent, ST),line_size([Sz1,Sz2])}
1179        end, CharsSizesL).
1180
1181insert_nl(CharsL, I, ST) ->
1182    insert_sep(CharsL, nl_indent(I, ST)).
1183
1184insert_sep([Chars1|CharsL], Sep) ->
1185    [Chars1 | [[Sep,Chars] || Chars <- CharsL]].
1186
1187nl_indent(0, _T) ->
1188    $\n;
1189nl_indent(I, T) when I > 0 ->
1190    [$\n|spaces(I, T)].
1191
1192classify_item({atom, _}) -> atomic;
1193classify_item({singleton_atom_type, _}) -> atomic;
1194classify_item(Atom) when is_atom(Atom) -> atomic;
1195classify_item({leaf, _, _}) -> atomic;
1196classify_item(_) -> complex.
1197
1198same_line(I0, SizeL, NSepChars, PP) ->
1199    try
1200        Size = lists:sum(SizeL) + NSepChars,
1201        true = incr(I0, Size) =< PP#pp.linewidth,
1202        {yes,Size}
1203    catch _:_ ->
1204        no
1205    end.
1206
1207line_size(SizeL) ->
1208    line_size(SizeL, 0, false).
1209
1210line_size([], Size, false) ->
1211    Size;
1212line_size([], Size, true) ->
1213    {line,Size};
1214line_size([{line,Len}|SizeL], _, _) ->
1215    line_size(SizeL, Len, true);
1216line_size([Sz|SizeL], SizeSoFar, LF) ->
1217    line_size(SizeL, SizeSoFar+Sz, LF).
1218
1219nsz({line,_Len}=Sz, _I) ->
1220    Sz;
1221nsz(Size, I) when I >= 0 ->
1222    {line,Size+I}.
1223
1224indent({_Chars,{line,Len}}, _I) ->
1225    Len;
1226indent({_Chars,Size}, I) ->
1227    incr(I, Size).
1228
1229incr(I, _Incr) when I < 0 ->
1230    I;
1231incr(I, Incr) ->
1232    I+Incr.
1233
1234indentation(E, I) when I < 0 ->
1235    string:length(E);
1236indentation(E, I0) ->
1237    I = io_lib_format:indentation(E, I0),
1238    case has_nl(E) of
1239        true -> {line,I};
1240        false -> I
1241    end.
1242
1243has_nl([$\n|_]) ->
1244    true;
1245has_nl([C|Cs]) when is_integer(C) ->
1246    has_nl(Cs);
1247has_nl([C|Cs]) ->
1248    has_nl(C) orelse has_nl(Cs);
1249has_nl([]) ->
1250    false.
1251
1252write_a_value(V, PP) ->
1253    flat_leaf(write_value(V, PP)).
1254
1255write_an_atom(A, PP) ->
1256    flat_leaf(write_atom(A, PP)).
1257
1258write_a_singleton_atom_type(A, PP) ->
1259    flat_leaf(write_singleton_atom_type(A, PP)).
1260
1261write_a_char(C, PP) ->
1262    flat_leaf(write_char(C, PP)).
1263
1264-define(MIN_SUBSTRING, 5).
1265
1266write_a_string(S, I, PP) when I < 0; S =:= [] ->
1267    flat_leaf(write_string(S, PP));
1268write_a_string(S, I, PP) ->
1269    Len = erlang:max(PP#pp.linewidth-I, ?MIN_SUBSTRING),
1270    {list,write_a_string(S, Len, Len, PP)}.
1271
1272write_a_string([], _N, _Len, _PP) ->
1273    [];
1274write_a_string(S, N, Len, PP) ->
1275    SS = string:slice(S, 0, N),
1276    Sl = write_string(SS, PP),
1277    case (string:length(Sl) > Len) and (N > ?MIN_SUBSTRING) of
1278        true ->
1279            write_a_string(S, N-1, Len, PP);
1280        false ->
1281            [flat_leaf(Sl) |
1282             write_a_string(string:slice(S, string:length(SS)), Len, Len, PP)]
1283    end.
1284
1285flat_leaf(S) ->
1286    L = lists:flatten(S),
1287    {leaf,string:length(L),L}.
1288
1289write_value(V, PP) ->
1290    (PP#pp.value_fun)(V).
1291
1292write_atom(A, PP) ->
1293    (PP#pp.value_fun)(A).
1294
1295write_singleton_atom_type(A, PP) ->
1296    (PP#pp.singleton_atom_type_fun)(A).
1297
1298write_string(S, PP) ->
1299    (PP#pp.string_fun)(S).
1300
1301write_char(C, PP) ->
1302    (PP#pp.char_fun)(C).
1303
1304%%
1305%% Utilities
1306%%
1307
1308a0() ->
1309    erl_anno:new(0).
1310
1311-define(N_SPACES, 30).
1312
1313spacetab() ->
1314    {[_|L],_} = mapfoldl(fun(_, A) -> {A,[$\s|A]}
1315                         end, [], lists:seq(0, ?N_SPACES)),
1316    list_to_tuple(L).
1317
1318spaces(N, T) when N =< ?N_SPACES ->
1319    element(N, T);
1320spaces(N, T) ->
1321    [element(?N_SPACES, T)|spaces(N-?N_SPACES, T)].
1322
1323wordtable() ->
1324    L = [begin {leaf,Sz,S} = leaf(W), {S,Sz} end ||
1325            W <- [" ->"," =","<<",">>","[]","after","begin","case","catch",
1326                  "end","fun","if","of","receive","try","when"," ::","..",
1327                  " |"]],
1328    list_to_tuple(L).
1329
1330word(' ->', WT) -> element(1, WT);
1331word(' =', WT) -> element(2, WT);
1332word('<<', WT) -> element(3, WT);
1333word('>>', WT) -> element(4, WT);
1334word('[]', WT) -> element(5, WT);
1335word('after', WT) -> element(6, WT);
1336word('begin', WT) -> element(7, WT);
1337word('case', WT) -> element(8, WT);
1338word('catch', WT) -> element(9, WT);
1339word('end', WT) -> element(10, WT);
1340word('fun', WT) -> element(11, WT);
1341word('if', WT) -> element(12, WT);
1342word('of', WT) -> element(13, WT);
1343word('receive', WT) -> element(14, WT);
1344word('try', WT) -> element(15, WT);
1345word('when', WT) -> element(16, WT);
1346word(' ::', WT) -> element(17, WT);
1347word('..', WT) -> element(18, WT);
1348word(' |', WT) -> element(19, WT).
1349