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, _Line} -> 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,Line,Name,Arg}, Opts) ->
266    lattribute({attribute,Line,Name,Arg}, Opts);
267lform({function,Line,Name,Arity,Clauses}, Opts) ->
268    lfunction({function,Line,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,_Line}, _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,_Line,type,Type}, Opts) ->
285    [typeattr(type, Type, Opts),leaf(".\n")];
286lattribute({attribute,_Line,opaque,Type}, Opts) ->
287    [typeattr(opaque, Type, Opts),leaf(".\n")];
288lattribute({attribute,_Line,spec,Arg}, _Opts) ->
289    [specattr(spec, Arg),leaf(".\n")];
290lattribute({attribute,_Line,callback,Arg}, _Opts) ->
291    [specattr(callback, Arg),leaf(".\n")];
292lattribute({attribute,_Line,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,Line}, _Opts) ->
315    attr(file, [{string,a0(),Name},{integer,a0(),Line}]);
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,_Line,[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,_Line,[T]}, P) ->
339    %% Generated before Erlang/OTP 18.
340    ltype(T, P);
341ltype({type,_Line,union,Ts}, Prec) ->
342    {_L,P,R} = type_inop_prec('|'),
343    E = {seq,[],[],[' |'],ltypes(Ts, R)},
344    maybe_paren(P, Prec, E);
345ltype({type,_Line,list,[T]}, _) ->
346    {seq,$[,$],$,,[ltype(T)]};
347ltype({type,_Line,nonempty_list,[T]}, _) ->
348    {seq,$[,$],[$,],[ltype(T),leaf("...")]};
349ltype({type,Line,nil,[]}, _) ->
350    lexpr({nil,Line}, options(none));
351ltype({type,Line,map,any}, _) ->
352    simple_type({atom,Line,map}, []);
353ltype({type,_Line,map,Pairs}, Prec) ->
354    {P,_R} = type_preop_prec('#'),
355    E = map_type(Pairs),
356    maybe_paren(P, Prec, E);
357ltype({type,Line,tuple,any}, _) ->
358    simple_type({atom,Line,tuple}, []);
359ltype({type,_Line,tuple,Ts}, _) ->
360    tuple_type(Ts, fun ltype/2);
361ltype({type,_Line,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,_Line,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,_Line,binary,[I1,I2]}, _) ->
371    binary_type(I1, I2); % except binary()
372ltype({type,_Line,'fun',[]}, _) ->
373    leaf("fun()");
374ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) ->
375    [fun_type(['fun',$(], FunType),$)];
376ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType, _) ->
377    [fun_type(['fun',$(], FunType),$)];
378ltype({type,Line,T,Ts}, _) ->
379    simple_type({atom,Line,T}, Ts);
380ltype({user_type,Line,T,Ts}, _) ->
381    simple_type({atom,Line,T}, Ts);
382ltype({remote_type,Line,[M,F,Ts]}, _) ->
383    simple_type({remote,Line,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,_Line,map_field_assoc,[KType,VType]}, Prec) ->
409    {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]};
410map_pair_type({type,_Line,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,_Line,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,_Line,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,_Line,constraint,[{atom,_,is_subtype},[{var,_,_}=V,Type]]},
454           _Opts) ->
455    typed(lexpr(V, options(none)), Type);
456constraint({type,_Line,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,_Line,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,_Line,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,Line,Head,Guard,Body}, Opts) ->
508    Hl = call({atom,Line,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    P = max_prec(),
553    Lcl = {list,[{step,[lexpr(E, P, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
554    {list,[{seq,$[,[],[[]],[{force_nl,leaf(" "),[Lcl]}]},$]]};
555    %% {list,[{step,$[,Lcl},$]]};
556lexpr({bc,_,E,Qs}, _Prec, Opts) ->
557    P = max_prec(),
558    Lcl = {list,[{step,[lexpr(E, P, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
559    {list,[{seq,'<<',[],[[]],[{force_nl,leaf(" "),[Lcl]}]},'>>']};
560    %% {list,[{step,'<<',Lcl},'>>']};
561lexpr({tuple,_,Elts}, _, Opts) ->
562    tuple(Elts, Opts);
563lexpr({record_index, _, Name, F}, Prec, Opts) ->
564    {P,R} = preop_prec('#'),
565    Nl = record_name(Name),
566    El = [Nl,$.,lexpr(F, R, Opts)],
567    maybe_paren(P, Prec, El);
568lexpr({record, _, Name, Fs}, Prec, Opts) ->
569    {P,_R} = preop_prec('#'),
570    Nl = record_name(Name),
571    El = {first,Nl,record_fields(Fs, Opts)},
572    maybe_paren(P, Prec, El);
573lexpr({record_field, _, Rec, Name, F}, Prec, Opts) ->
574    {L,P,R} = inop_prec('#'),
575    Rl = lexpr(Rec, L, Opts),
576    Sep = hash_after_integer(Rec, [$#]),
577    Nl = [Sep,{atom,Name},$.],
578    El = [Rl,Nl,lexpr(F, R, Opts)],
579    maybe_paren(P, Prec, El);
580lexpr({record, _, Rec, Name, Fs}, Prec, Opts) ->
581    {L,P,_R} = inop_prec('#'),
582    Rl = lexpr(Rec, L, Opts),
583    Sep = hash_after_integer(Rec, []),
584    Nl = record_name(Name),
585    El = {first,[Rl,Sep,Nl],record_fields(Fs, Opts)},
586    maybe_paren(P, Prec, El);
587lexpr({record_field, _, {atom,_,''}, F}, Prec, Opts) ->
588    {_L,P,R} = inop_prec('.'),
589    El = [$.,lexpr(F, R, Opts)],
590    maybe_paren(P, Prec, El);
591lexpr({record_field, _, Rec, F}, Prec, Opts) ->
592    {L,P,R} = inop_prec('.'),
593    El = [lexpr(Rec, L, Opts),$.,lexpr(F, R, Opts)],
594    maybe_paren(P, Prec, El);
595lexpr({map, _, Fs}, Prec, Opts) ->
596    {P,_R} = preop_prec('#'),
597    El = {first,$#,map_fields(Fs, Opts)},
598    maybe_paren(P, Prec, El);
599lexpr({map, _, Map, Fs}, Prec, Opts) ->
600    {L,P,_R} = inop_prec('#'),
601    Rl = lexpr(Map, L, Opts),
602    Sep = hash_after_integer(Map, [$#]),
603    El = {first,[Rl|Sep],map_fields(Fs, Opts)},
604    maybe_paren(P, Prec, El);
605lexpr({block,_,Es}, _, Opts) ->
606    {list,[{step,'begin',body(Es, Opts)},{reserved,'end'}]};
607lexpr({'if',_,Cs}, _, Opts) ->
608    {list,[{step,'if',if_clauses(Cs, Opts)},{reserved,'end'}]};
609lexpr({'case',_,Expr,Cs}, _, Opts) ->
610    {list,[{step,{list,[{step,'case',lexpr(Expr, Opts)},{reserved,'of'}]},
611            cr_clauses(Cs, Opts)},
612           {reserved,'end'}]};
613lexpr({'cond',_,Cs}, _, Opts) ->
614    {list,[{step,leaf("cond"),cond_clauses(Cs, Opts)},{reserved,'end'}]};
615lexpr({'receive',_,Cs}, _, Opts) ->
616    {list,[{step,'receive',cr_clauses(Cs, Opts)},{reserved,'end'}]};
617lexpr({'receive',_,Cs,To,ToOpt}, _, Opts) ->
618    Al = {list,[{step,[lexpr(To, Opts),' ->'],body(ToOpt, Opts)}]},
619    {list,[{step,'receive',cr_clauses(Cs, Opts)},
620           {step,'after',Al},
621           {reserved,'end'}]};
622lexpr({'fun',_,{function,F,A}}, _Prec, _Opts) ->
623    [leaf("fun "),{atom,F},leaf(format("/~w", [A]))];
624lexpr({'fun',L,{function,_,_}=Func,Extra}, Prec, Opts) ->
625    {force_nl,fun_info(Extra),lexpr({'fun',L,Func}, Prec, Opts)};
626lexpr({'fun',L,{function,M,F,A}}, Prec, Opts)
627  when is_atom(M), is_atom(F), is_integer(A) ->
628    %% For backward compatibility with pre-R15 abstract format.
629    Mod = erl_parse:abstract(M),
630    Fun = erl_parse:abstract(F),
631    Arity = erl_parse:abstract(A),
632    lexpr({'fun',L,{function,Mod,Fun,Arity}}, Prec, Opts);
633lexpr({'fun',_,{function,M,F,A}}, _Prec, Opts) ->
634    %% New format in R15.
635    NameItem = lexpr(M, Opts),
636    CallItem = lexpr(F, Opts),
637    ArityItem = lexpr(A, Opts),
638    ["fun ",NameItem,$:,CallItem,$/,ArityItem];
639lexpr({'fun',_,{clauses,Cs}}, _Prec, Opts) ->
640    {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]};
641lexpr({named_fun,_,Name,Cs}, _Prec, Opts) ->
642    {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
643           {reserved,'end'}]};
644lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
645    {force_nl,fun_info(Extra),
646     {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]}};
647lexpr({named_fun,_,Name,Cs,Extra}, _Prec, Opts) ->
648    {force_nl,fun_info(Extra),
649     {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
650            {reserved,'end'}]}};
651lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
652    case erl_internal:bif(M, F, length(Args)) of
653        true when F =/= float ->
654            call(N, Args, Prec, Opts);
655        true ->
656            call(Name, Args, Prec, Opts);
657        false ->
658            call(Name, Args, Prec, Opts)
659    end;
660lexpr({call,_,Name,Args}, Prec, Opts) ->
661    call(Name, Args, Prec, Opts);
662lexpr({'try',_,Es,Scs,Ccs,As}, _, Opts) ->
663    {list,[if
664               Scs =:= [] ->
665                   {step,'try',body(Es, Opts)};
666               true ->
667                   {step,{list,[{step,'try',body(Es, Opts)},{reserved,'of'}]},
668                    cr_clauses(Scs, Opts)}
669           end] ++
670           if
671               Ccs =:= [] ->
672                   [];
673               true ->
674                   [{step,'catch',try_clauses(Ccs, Opts)}]
675           end ++
676           if
677               As =:= [] ->
678                   [];
679               true ->
680                   [{step,'after',body(As, Opts)}]
681           end ++
682           [{reserved,'end'}]};
683lexpr({'catch',_,Expr}, Prec, Opts) ->
684    {P,R} = preop_prec('catch'),
685    El = {list,[{step,'catch',lexpr(Expr, R, Opts)}]},
686    maybe_paren(P, Prec, El);
687lexpr({match,_,Lhs,Rhs}, Prec, Opts) ->
688    {L,P,R} = inop_prec('='),
689    Pl = lexpr(Lhs, L, Opts),
690    Rl = lexpr(Rhs, R, Opts),
691    El = {list,[{cstep,[Pl,' ='],Rl}]},
692    maybe_paren(P, Prec, El);
693lexpr({op,_,Op,Arg}, Prec, Opts) ->
694    {P,R} = preop_prec(Op),
695    Ol = {reserved, leaf(format("~s ", [Op]))},
696    El = [Ol,lexpr(Arg, R, Opts)],
697    maybe_paren(P, Prec, El);
698lexpr({op,_,Op,Larg,Rarg}, Prec, Opts)  when Op =:= 'orelse';
699                                             Op =:= 'andalso' ->
700    %% Breaks lines since R12B.
701    {L,P,R} = inop_prec(Op),
702    Ll = lexpr(Larg, L, Opts),
703    Ol = {reserved, leaf(format("~s", [Op]))},
704    Lr = lexpr(Rarg, R, Opts),
705    El = {prefer_nl,[[]],[Ll,Ol,Lr]},
706    maybe_paren(P, Prec, El);
707lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) ->
708    {L,P,R} = inop_prec(Op),
709    Ll = lexpr(Larg, L, Opts),
710    Ol = {reserved, leaf(format("~s", [Op]))},
711    Lr = lexpr(Rarg, R, Opts),
712    El = {list,[Ll,Ol,Lr]},
713    maybe_paren(P, Prec, El);
714%% Special expressions which are not really legal everywhere.
715lexpr({remote,_,M,F}, Prec, Opts) ->
716    {L,P,R} = inop_prec(':'),
717    NameItem = lexpr(M, L, Opts),
718    CallItem = lexpr(F, R, Opts),
719    maybe_paren(P, Prec, [NameItem,$:,CallItem]);
720%% BIT SYNTAX:
721lexpr({bin,_,Fs}, _, Opts) ->
722    bit_grp(Fs, Opts);
723%% Special case for straight values.
724lexpr({value,_,Val}, _,_) ->
725    {value,Val};
726%% Now do the hook.
727lexpr(Other, _Precedence, #options{hook = none}) ->
728    leaf(format("INVALID-FORM:~w:",[Other]));
729lexpr(HookExpr, Precedence, #options{hook = {Mod,Func,Eas}})
730                                        when Mod =/= 'fun' ->
731    {ehook,HookExpr,Precedence,{Mod,Func,Eas}};
732lexpr(HookExpr, Precedence, #options{hook = Func, opts = Options}) ->
733    {hook,HookExpr,Precedence,Func,Options}.
734
735%% An integer is separated from the following '#' by a space, which
736%% erl_scan can handle.
737hash_after_integer({integer, _, _}, C) ->
738    [$\s|C];
739hash_after_integer({'fun',_,{function, _, _}}, C) ->
740    [$\s|C];
741hash_after_integer({'fun',_,{function, _, _, _}}, C) ->
742    [$\s|C];
743hash_after_integer(_, C) ->
744    C.
745
746call(Name, Args, Prec, Opts) ->
747    {F,P} = func_prec(),
748    Item = {first,lexpr(Name, F, Opts),args(Args, Opts)},
749    maybe_paren(P, Prec, Item).
750
751fun_info(Extra) ->
752    [leaf("% fun-info: "),{value,Extra}].
753
754%% BITS:
755
756bit_grp([], _Opts) ->
757    leaf("<<>>");
758bit_grp(Fs, Opts) ->
759    append([['<<'], [bit_elems(Fs, Opts)], ['>>']]).
760
761bit_elems(Es, Opts) ->
762    expr_list(Es, $,, fun bit_elem/2, Opts).
763
764bit_elem({bin_element,_,Expr,Sz,Types}, Opts) ->
765    P = max_prec(),
766    VChars = lexpr(Expr, P, Opts),
767    SChars = if
768                 Sz =/= default ->
769                     [VChars,$:,lexpr(Sz, P, Opts)];
770                 true ->
771                     VChars
772             end,
773    if
774        Types =/= default ->
775            [SChars,$/|bit_elem_types(Types)];
776        true ->
777            SChars
778    end.
779
780bit_elem_types([T]) ->
781    [bit_elem_type(T)];
782bit_elem_types([T | Rest]) ->
783    [bit_elem_type(T), $-|bit_elem_types(Rest)].
784
785bit_elem_type({A,B}) ->
786    [lexpr(erl_parse:abstract(A), options(none)),
787     $:,
788     lexpr(erl_parse:abstract(B), options(none))];
789bit_elem_type(T) ->
790    lexpr(erl_parse:abstract(T), options(none)).
791
792%% end of BITS
793
794record_name(Name) ->
795    [$#,{atom,Name}].
796
797record_fields(Fs, Opts) ->
798    tuple(Fs, fun record_field/2, Opts).
799
800record_field({record_field,_,F,Val}, Opts) ->
801    {L,_P,R} = inop_prec('='),
802    Fl = lexpr(F, L, Opts),
803    Vl = lexpr(Val, R, Opts),
804    {list,[{cstep,[Fl,' ='],Vl}]};
805record_field({typed_record_field,{record_field,_,F,Val},Type}, Opts) ->
806    {L,_P,R} = inop_prec('='),
807    Fl = lexpr(F, L, Opts),
808    Vl = typed(lexpr(Val, R, Opts), Type),
809    {list,[{cstep,[Fl,' ='],Vl}]};
810record_field({typed_record_field,Field,Type}, Opts) ->
811    typed(record_field(Field, Opts), Type);
812record_field({record_field,_,F}, Opts) ->
813    lexpr(F, 0, Opts).
814
815map_fields(Fs, Opts) ->
816    tuple(Fs, fun map_field/2, Opts).
817
818map_field({map_field_assoc,_,K,V}, Opts) ->
819    Pl = lexpr(K, 0, Opts),
820    {list,[{step,[Pl,leaf(" =>")],lexpr(V, 0, Opts)}]};
821map_field({map_field_exact,_,K,V}, Opts) ->
822    Pl = lexpr(K, 0, Opts),
823    {list,[{step,[Pl,leaf(" :=")],lexpr(V, 0, Opts)}]}.
824
825list({cons,_,H,T}, Es, Opts) ->
826    list(T, [H|Es], Opts);
827list({nil,_}, Es, Opts) ->
828    proper_list(reverse(Es), Opts);
829list(Other, Es, Opts) ->
830    improper_list(reverse(Es, [Other]), Opts).
831
832%% if_clauses(Clauses, Opts) -> [Char].
833%%  Print 'if' clauses.
834
835if_clauses(Cs, Opts) ->
836    clauses(fun if_clause/2, Opts, Cs).
837
838if_clause({clause,_,[],G,B}, Opts) ->
839    Gl = [guard_no_when(G, Opts),' ->'],
840    {step,Gl,body(B, Opts)}.
841
842guard_no_when([E|Es], Opts) when is_list(E) ->
843    expr_list([E|Es], $;, fun guard0/2, Opts);
844guard_no_when([E|Es], Opts) -> % before R6
845    guard_no_when([[E|Es]], Opts);
846guard_no_when([], _) -> % cannot happen
847    leaf("true").
848
849%% cr_clauses(Clauses, Opts) -> [Char].
850%%  Print 'case'/'receive' clauses.
851
852cr_clauses(Cs, Opts) ->
853    clauses(fun cr_clause/2, Opts, Cs).
854
855cr_clause({clause,_,[T],G,B}, Opts) ->
856    El = lexpr(T, 0, Opts),
857    Gl = guard_when(El, G, Opts),
858    Bl = body(B, Opts),
859    {step,Gl,Bl}.
860
861%% try_clauses(Clauses, Opts) -> [Char].
862%%  Print 'try' clauses.
863
864try_clauses(Cs, Opts) ->
865    clauses(fun try_clause/2, Opts, Cs).
866
867try_clause({clause,_,[{tuple,_,[C,V,S]}],G,B}, Opts) ->
868    Cs = lexpr(C, 0, Opts),
869    El = lexpr(V, 0, Opts),
870    CsEl = [Cs,$:,El],
871    Sl = stack_backtrace(S, CsEl, Opts),
872    Gl = guard_when(Sl, G, Opts),
873    Bl = body(B, Opts),
874    {step,Gl,Bl}.
875
876stack_backtrace({var,_,'_'}, El, _Opts) ->
877    El;
878stack_backtrace(S, El, Opts) ->
879    El++[$:,lexpr(S, 0, Opts)].
880
881%% fun_clauses(Clauses, Opts) -> [Char].
882%%  Print 'fun' clauses.
883
884fun_clauses(Cs, Opts, unnamed) ->
885    nl_clauses(fun fun_clause/2, [$;], Opts, Cs);
886fun_clauses(Cs, Opts, {named, Name}) ->
887    nl_clauses(fun (C, H) ->
888                       {step,Gl,Bl} = fun_clause(C, H),
889                       {step,[atom_to_list(Name),Gl],Bl}
890               end, [$;], Opts, Cs).
891
892fun_clause({clause,_,A,G,B}, Opts) ->
893    El = args(A, Opts),
894    Gl = guard_when(El, G, Opts),
895    Bl = body(B, Opts),
896    {step,Gl,Bl}.
897
898%% cond_clauses(Clauses, Opts) -> [Char].
899%%  Print 'cond' clauses.
900
901cond_clauses(Cs, Opts) ->
902    clauses(fun cond_clause/2, Opts, Cs).
903
904cond_clause({clause,_,[],[[E]],B}, Opts) ->
905    {step,[lexpr(E, Opts),' ->'],body(B, Opts)}.
906
907%% nl_clauses(Type, Opts, Clauses) -> [Char].
908%%  Generic clause printing function (always breaks lines).
909
910nl_clauses(Type, Sep, Opts, Cs) ->
911    {prefer_nl,Sep,lexprs(Cs, Type, Opts)}.
912
913%% clauses(Type, Opts, Clauses) -> [Char].
914%%  Generic clause printing function (breaks lines since R12B).
915
916clauses(Type, Opts, Cs) ->
917    {prefer_nl,[$;],lexprs(Cs, Type, Opts)}.
918
919%% lc_quals(Qualifiers, After, Opts)
920%% List comprehension qualifiers (breaks lines since R12B).
921
922lc_quals(Qs, Opts) ->
923    {prefer_nl,[$,],lexprs(Qs, fun lc_qual/2, Opts)}.
924
925lc_qual({b_generate,_,Pat,E}, Opts) ->
926    Pl = lexpr(Pat, 0, Opts),
927    {list,[{step,[Pl,leaf(" <=")],lexpr(E, 0, Opts)}]};
928lc_qual({generate,_,Pat,E}, Opts) ->
929    Pl = lexpr(Pat, 0, Opts),
930    {list,[{step,[Pl,leaf(" <-")],lexpr(E, 0, Opts)}]};
931lc_qual(Q, Opts) ->
932    lexpr(Q, 0, Opts).
933
934proper_list(Es, Opts) ->
935    {seq,$[,$],[$,],lexprs(Es, Opts)}.
936
937improper_list(Es, Opts) ->
938    {seq,$[,$],[{$,,' |'}],lexprs(Es, Opts)}.
939
940tuple(L, Opts) ->
941    tuple(L, fun lexpr/2, Opts).
942
943tuple([], _F, _Opts) ->
944    leaf("{}");
945tuple(Es, F, Opts) ->
946    {seq,${,$},[$,],lexprs(Es, F, Opts)}.
947
948args(As, Opts) ->
949    {seq,$(,$),[$,],lexprs(As, Opts)}.
950
951expr_list(Es, Sep, F, Opts) ->
952    {seq,[],[],Sep,lexprs(Es, F, Opts)}.
953
954lexprs(Es, Opts) ->
955    lexprs(Es, fun lexpr/2, Opts).
956
957lexprs(Es, F, Opts) ->
958    [F(E, Opts) || E <- Es].
959
960maybe_paren(P, Prec, Expr) when P < Prec ->
961    [$(,Expr,$)];
962maybe_paren(_P, _Prec, Expr) ->
963    Expr.
964
965leaf(S) ->
966    {leaf,string:length(S),S}.
967
968%%% Do the formatting. Currently nothing fancy. Could probably have
969%%% done it in one single pass.
970
971frmt(Item, PP) ->
972    frmt(Item, 0, PP).
973
974frmt(Item, I, PP) ->
975    ST = spacetab(),
976    WT = wordtable(),
977    {Chars,_Length} = f(Item, I, ST, WT, PP),
978    [Chars].
979
980%%% What the tags mean:
981%%% - C: a character
982%%% - [I|Is]: Is follow after I without newline or space
983%%% - {list,IPs}: try to put all IPs on one line, if that fails newlines
984%%%   and indentation are inserted between IPs.
985%%% - {first,I,IP2}: IP2 follows after I, and is output with an indentation
986%%%   updated with the width of I.
987%%% - {seq,Before,After,Separator,IPs}: a sequence of Is separated by
988%%%   Separator. Before is output before IPs, and the indentation of IPs
989%%%   is updated with the width of Before. After follows after IPs.
990%%% - {force_nl,ExtraInfo,I}: fun-info (a comment) forces linebreak before I.
991%%% - {prefer_nl,Sep,IPs}: forces linebreak between Is unlesss negative
992%%%   indentation.
993%%% - {atom,A}: an atom
994%%% - {singleton_atom_type,A}: a singleton atom type
995%%% - {char,C}: a character
996%%% - {string,S}: a string.
997%%% - {value,T}: a term.
998%%% - {hook,...}, {ehook,...}: hook expressions.
999%%%
1000%%% list, first, seq, force_nl, and prefer_nl all accept IPs, where each
1001%%% element is either an item or a tuple {step|cstep,I1,I2}. step means
1002%%% that I2 is output after linebreak and an incremented indentation.
1003%%% cstep works similarly, but no linebreak if the width of I1 is less
1004%%% than the indentation (this is for "A = <expression over several lines>).
1005
1006f([]=Nil, _I0, _ST, _WT, _PP) ->
1007    {Nil,0};
1008f(C, _I0, _ST, _WT, _PP) when is_integer(C) ->
1009    {C,1};
1010f({leaf,Length,Chars}, _I0, _ST, _WT, _PP) ->
1011    {Chars,Length};
1012f([Item|Items], I0, ST, WT, PP) ->
1013    consecutive(Items, f(Item, I0, ST, WT, PP), I0, ST, WT, PP);
1014f({list,Items}, I0, ST, WT, PP) ->
1015    f({seq,[],[],[[]],Items}, I0, ST, WT, PP);
1016f({first,E,Item}, I0, ST, WT, PP) ->
1017    f({seq,E,[],[[]],[Item]}, I0, ST, WT, PP);
1018f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) ->
1019    BCharsSize = f(Before, I0, ST, WT, PP),
1020    I = indent(BCharsSize, I0),
1021    CharsSizeL = fl(LItems, Sep, I, After, ST, WT, PP),
1022    {CharsL,SizeL} = unz(CharsSizeL),
1023    {BCharsL,BSizeL} = unz1([BCharsSize]),
1024    Sizes = BSizeL ++ SizeL,
1025    NSepChars = if
1026                    is_list(Sep), Sep =/= [] ->
1027                        erlang:max(0, length(CharsL)-1); % not string:length
1028                    true ->
1029                        0
1030                end,
1031    case same_line(I0, Sizes, NSepChars, PP) of
1032        {yes,Size} ->
1033            Chars = if
1034                        NSepChars > 0 -> insert_sep(CharsL, $\s);
1035                        true -> CharsL
1036                    end,
1037            {BCharsL++Chars,Size};
1038        no ->
1039            CharsList = handle_step(CharsSizeL, I, ST, PP),
1040            {LChars, LSize} =
1041                maybe_newlines(CharsList, LItems, I, NSepChars, ST, PP),
1042            {[BCharsL,LChars],nsz(LSize, I0)}
1043    end;
1044f({force_nl,_ExtraInfoItem,Item}, I, ST, WT, PP) when I < 0 ->
1045    %% Extra info is a comment; cannot have that on the same line
1046    f(Item, I, ST, WT, PP);
1047f({force_nl,ExtraInfoItem,Item}, I, ST, WT, PP) ->
1048    f({prefer_nl,[],[ExtraInfoItem,Item]}, I, ST, WT, PP);
1049f({prefer_nl,Sep,LItems}, I, ST, WT, PP) when I < 0 ->
1050    f({seq,[],[],Sep,LItems}, I, ST, WT, PP);
1051f({prefer_nl,Sep,LItems}, I0, ST, WT, PP) ->
1052    CharsSize2L = fl(LItems, Sep, I0, [], ST, WT, PP),
1053    {_CharsL,Sizes} = unz(CharsSize2L),
1054    if
1055        Sizes =:= [] ->
1056            {[], 0};
1057        true ->
1058            {insert_newlines(CharsSize2L, I0, ST, PP),
1059             nsz(lists:last(Sizes), I0)}
1060    end;
1061f({value,V}, I, ST, WT, PP) ->
1062    f(write_a_value(V, PP), I, ST, WT, PP);
1063f({atom,A}, I, ST, WT, PP) ->
1064    f(write_an_atom(A, PP), I, ST, WT, PP);
1065f({singleton_atom_type,A}, I, ST, WT, PP) ->
1066    f(write_a_singleton_atom_type(A, PP), I, ST, WT, PP);
1067f({char,C}, I, ST, WT, PP) ->
1068    f(write_a_char(C, PP), I, ST, WT, PP);
1069f({string,S}, I, ST, WT, PP) ->
1070    f(write_a_string(S, I, PP), I, ST, WT, PP);
1071f({reserved,R}, I, ST, WT, PP) ->
1072    f(R, I, ST, WT, PP);
1073f({hook,HookExpr,Precedence,Func,Options}, I, _ST, _WT, _PP) ->
1074    Chars = Func(HookExpr, I, Precedence, Options),
1075    {Chars,indentation(Chars, I)};
1076f({ehook,HookExpr,Precedence,{Mod,Func,Eas}=ModFuncEas}, I, _ST, _WT, _PP) ->
1077    Chars = apply(Mod, Func, [HookExpr,I,Precedence,ModFuncEas|Eas]),
1078    {Chars,indentation(Chars, I)};
1079f(WordName, _I, _ST, WT, _PP) when is_atom(WordName) ->
1080    word(WordName, WT).
1081
1082%% fl(ListItems, I0, ST, WT) -> [[CharsSize1,CharsSize2]]
1083%% ListItems = [{Item,Items}|Item]
1084fl([], _Sep, I0, After, ST, WT, PP) ->
1085    [[f(After, I0, ST, WT, PP),{[],0}]];
1086fl(CItems, Sep0, I0, After, ST, WT, PP) ->
1087    F = fun({step,Item1,Item2}, S) ->
1088                [f(Item1, I0, ST, WT, PP),
1089                 f([Item2,S], incr(I0, PP#pp.indent), ST, WT, PP)];
1090           ({cstep,Item1,Item2}, S) ->
1091                {_,Sz1} = CharSize1 = f(Item1, I0, ST, WT, PP),
1092                if
1093                    is_integer(Sz1), Sz1 < PP#pp.indent ->
1094                        Item2p = [leaf("\s"),Item2,S],
1095                        [consecutive(Item2p, CharSize1, I0, ST, WT, PP),{[],0}];
1096                    true ->
1097                        [CharSize1,f([Item2,S], incr(I0, PP#pp.indent), ST, WT, PP)]
1098                end;
1099           ({reserved,Word}, S) ->
1100                [f([Word,S], I0, ST, WT, PP),{[],0}];
1101           (Item, S) ->
1102                [f([Item,S], I0, ST, WT, PP),{[],0}]
1103        end,
1104    {Sep,LastSep} = sep(Sep0),
1105    fl1(CItems, F, Sep, LastSep, After).
1106
1107sep([{S,LS}]) -> {[S],[LS]};
1108sep({_,_}=Sep) -> Sep;
1109sep(S) -> {S, S}.
1110
1111fl1([CItem], F, _Sep, _LastSep, After) ->
1112    [F(CItem,After)];
1113fl1([CItem1,CItem2], F, _Sep, LastSep, After) ->
1114    [F(CItem1, LastSep),F(CItem2, After)];
1115fl1([CItem|CItems], F, Sep, LastSep, After) ->
1116    [F(CItem, Sep)|fl1(CItems, F, Sep, LastSep, After)].
1117
1118consecutive(Items, CharSize1, I0, ST, WT, PP) ->
1119    {CharsSizes,_Length} =
1120        mapfoldl(fun(Item, Len) ->
1121                         CharsSize = f(Item, Len, ST, WT, PP),
1122                         {CharsSize,indent(CharsSize, Len)}
1123                 end, indent(CharSize1, I0), Items),
1124    {CharsL,SizeL} = unz1([CharSize1|CharsSizes]),
1125    {CharsL,line_size(SizeL)}.
1126
1127unz(CharsSizesL) ->
1128    unz1(append(CharsSizesL)).
1129
1130unz1(CharSizes) ->
1131    lists:unzip(nonzero(CharSizes)).
1132
1133nonzero(CharSizes) ->
1134    lists:filter(fun({_,Sz}) -> Sz =/= 0 end, CharSizes).
1135
1136maybe_newlines([{Chars,Size}], [], _I, _NSepChars, _ST, _PP) ->
1137    {Chars,Size};
1138maybe_newlines(CharsSizeList, Items, I, NSepChars, ST, PP) when I >= 0 ->
1139    maybe_sep(CharsSizeList, Items, I, NSepChars, nl_indent(I, ST), PP).
1140
1141maybe_sep([{Chars1,Size1}|CharsSizeL], [Item|Items], I0, NSepChars, Sep, PP) ->
1142    I1 = case classify_item(Item) of
1143             atomic ->
1144                 I0 + Size1;
1145             _ ->
1146                 PP#pp.linewidth+1
1147         end,
1148    maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars, Size1, [Chars1], PP).
1149
1150maybe_sep1([{Chars,Size}|CharsSizeL], [Item|Items],
1151           I0, I, Sep, NSepChars, Sz0, A, PP) ->
1152    case classify_item(Item) of
1153        atomic when is_integer(Size) ->
1154            Size1 = Size + 1,
1155            I1 = I + Size1,
1156            if
1157                I1 =< PP#pp.linewidth ->
1158                    A1 = if
1159                             NSepChars > 0 -> [Chars,$\s|A];
1160                             true -> [Chars|A]
1161                         end,
1162                    maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars,
1163                               Sz0 + Size1, A1, PP);
1164                true ->
1165                    A1 = [Chars,Sep|A],
1166                    maybe_sep1(CharsSizeL, Items, I0, I0 + Size, Sep,
1167                               NSepChars, Size1, A1, PP)
1168            end;
1169        _ ->
1170            A1 = [Chars,Sep|A],
1171            maybe_sep1(CharsSizeL, Items, I0, PP#pp.linewidth+1, Sep, NSepChars,
1172                       0, A1, PP)
1173    end;
1174maybe_sep1(_CharsSizeL, _Items, _Io, _I, _Sep, _NSepChars, Sz, A, _PP) ->
1175    {lists:reverse(A), Sz}.
1176
1177insert_newlines(CharsSizesL, I, ST, PP) when I >= 0 ->
1178    {CharsL, _} = unz1(handle_step(CharsSizesL, I, ST, PP)),
1179    insert_nl(CharsL, I, ST).
1180
1181handle_step(CharsSizesL, I, ST, PP) ->
1182    map(fun([{_C1,0},{_C2,0}]) ->
1183                {[], 0};
1184           ([{C1,Sz1},{_C2,0}]) ->
1185                {C1, Sz1};
1186           ([{C1,Sz1},{C2,Sz2}]) when Sz2 > 0 ->
1187                {insert_nl([C1,C2], I+PP#pp.indent, ST),line_size([Sz1,Sz2])}
1188        end, CharsSizesL).
1189
1190insert_nl(CharsL, I, ST) ->
1191    insert_sep(CharsL, nl_indent(I, ST)).
1192
1193insert_sep([Chars1|CharsL], Sep) ->
1194    [Chars1 | [[Sep,Chars] || Chars <- CharsL]].
1195
1196nl_indent(0, _T) ->
1197    $\n;
1198nl_indent(I, T) when I > 0 ->
1199    [$\n|spaces(I, T)].
1200
1201classify_item({atom, _}) -> atomic;
1202classify_item({singleton_atom_type, _}) -> atomic;
1203classify_item(Atom) when is_atom(Atom) -> atomic;
1204classify_item({leaf, _, _}) -> atomic;
1205classify_item(_) -> complex.
1206
1207same_line(I0, SizeL, NSepChars, PP) ->
1208    try
1209        Size = lists:sum(SizeL) + NSepChars,
1210        true = incr(I0, Size) =< PP#pp.linewidth,
1211        {yes,Size}
1212    catch _:_ ->
1213        no
1214    end.
1215
1216line_size(SizeL) ->
1217    line_size(SizeL, 0, false).
1218
1219line_size([], Size, false) ->
1220    Size;
1221line_size([], Size, true) ->
1222    {line,Size};
1223line_size([{line,Len}|SizeL], _, _) ->
1224    line_size(SizeL, Len, true);
1225line_size([Sz|SizeL], SizeSoFar, LF) ->
1226    line_size(SizeL, SizeSoFar+Sz, LF).
1227
1228nsz({line,_Len}=Sz, _I) ->
1229    Sz;
1230nsz(Size, I) when I >= 0 ->
1231    {line,Size+I}.
1232
1233indent({_Chars,{line,Len}}, _I) ->
1234    Len;
1235indent({_Chars,Size}, I) ->
1236    incr(I, Size).
1237
1238incr(I, _Incr) when I < 0 ->
1239    I;
1240incr(I, Incr) ->
1241    I+Incr.
1242
1243indentation(E, I) when I < 0 ->
1244    string:length(E);
1245indentation(E, I0) ->
1246    I = io_lib_format:indentation(E, I0),
1247    case has_nl(E) of
1248        true -> {line,I};
1249        false -> I
1250    end.
1251
1252has_nl([$\n|_]) ->
1253    true;
1254has_nl([C|Cs]) when is_integer(C) ->
1255    has_nl(Cs);
1256has_nl([C|Cs]) ->
1257    has_nl(C) orelse has_nl(Cs);
1258has_nl([]) ->
1259    false.
1260
1261write_a_value(V, PP) ->
1262    flat_leaf(write_value(V, PP)).
1263
1264write_an_atom(A, PP) ->
1265    flat_leaf(write_atom(A, PP)).
1266
1267write_a_singleton_atom_type(A, PP) ->
1268    flat_leaf(write_singleton_atom_type(A, PP)).
1269
1270write_a_char(C, PP) ->
1271    flat_leaf(write_char(C, PP)).
1272
1273-define(MIN_SUBSTRING, 5).
1274
1275write_a_string(S, I, PP) when I < 0; S =:= [] ->
1276    flat_leaf(write_string(S, PP));
1277write_a_string(S, I, PP) ->
1278    Len = erlang:max(PP#pp.linewidth-I, ?MIN_SUBSTRING),
1279    {list,write_a_string(S, Len, Len, PP)}.
1280
1281write_a_string([], _N, _Len, _PP) ->
1282    [];
1283write_a_string(S, N, Len, PP) ->
1284    SS = string:slice(S, 0, N),
1285    Sl = write_string(SS, PP),
1286    case (string:length(Sl) > Len) and (N > ?MIN_SUBSTRING) of
1287        true ->
1288            write_a_string(S, N-1, Len, PP);
1289        false ->
1290            [flat_leaf(Sl) |
1291             write_a_string(string:slice(S, string:length(SS)), Len, Len, PP)]
1292    end.
1293
1294flat_leaf(S) ->
1295    L = lists:flatten(S),
1296    {leaf,string:length(L),L}.
1297
1298write_value(V, PP) ->
1299    (PP#pp.value_fun)(V).
1300
1301write_atom(A, PP) ->
1302    (PP#pp.value_fun)(A).
1303
1304write_singleton_atom_type(A, PP) ->
1305    (PP#pp.singleton_atom_type_fun)(A).
1306
1307write_string(S, PP) ->
1308    (PP#pp.string_fun)(S).
1309
1310write_char(C, PP) ->
1311    (PP#pp.char_fun)(C).
1312
1313%%
1314%% Utilities
1315%%
1316
1317a0() ->
1318    erl_anno:new(0).
1319
1320-define(N_SPACES, 30).
1321
1322spacetab() ->
1323    {[_|L],_} = mapfoldl(fun(_, A) -> {A,[$\s|A]}
1324                         end, [], lists:seq(0, ?N_SPACES)),
1325    list_to_tuple(L).
1326
1327spaces(N, T) when N =< ?N_SPACES ->
1328    element(N, T);
1329spaces(N, T) ->
1330    [element(?N_SPACES, T)|spaces(N-?N_SPACES, T)].
1331
1332wordtable() ->
1333    L = [begin {leaf,Sz,S} = leaf(W), {S,Sz} end ||
1334            W <- [" ->"," =","<<",">>","[]","after","begin","case","catch",
1335                  "end","fun","if","of","receive","try","when"," ::","..",
1336                  " |"]],
1337    list_to_tuple(L).
1338
1339word(' ->', WT) -> element(1, WT);
1340word(' =', WT) -> element(2, WT);
1341word('<<', WT) -> element(3, WT);
1342word('>>', WT) -> element(4, WT);
1343word('[]', WT) -> element(5, WT);
1344word('after', WT) -> element(6, WT);
1345word('begin', WT) -> element(7, WT);
1346word('case', WT) -> element(8, WT);
1347word('catch', WT) -> element(9, WT);
1348word('end', WT) -> element(10, WT);
1349word('fun', WT) -> element(11, WT);
1350word('if', WT) -> element(12, WT);
1351word('of', WT) -> element(13, WT);
1352word('receive', WT) -> element(14, WT);
1353word('try', WT) -> element(15, WT);
1354word('when', WT) -> element(16, WT);
1355word(' ::', WT) -> element(17, WT);
1356word('..', WT) -> element(18, WT);
1357word(' |', WT) -> element(19, WT).
1358