1%% Licensed under the Apache License, Version 2.0 (the "License");
2%% you may not use this file except in compliance with the License.
3%% You may obtain a copy of the License at
4%%
5%%     http://www.apache.org/licenses/LICENSE-2.0
6%%
7%% Unless required by applicable law or agreed to in writing, software
8%% distributed under the License is distributed on an "AS IS" BASIS,
9%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10%% See the License for the specific language governing permissions and
11%% limitations under the License.
12%%
13%% @copyright 1999-2002 Richard Carlsson
14%% @author Richard Carlsson <carlsson.richard@gmail.com>
15%% @doc Core Erlang prettyprinter.
16%%
17%% <p>This module is a front end to the pretty-printing library module
18%% <code>prettypr</code>, for text formatting of Core Erlang abstract
19%% syntax trees defined by the module <code>cerl</code>.</p>
20
21%% TODO: add printing of comments for `comment'-annotations?
22
23-module(cerl_prettypr).
24
25-define(NO_UNUSED, true).
26
27-export([format/1, format/2, annotate/3]).
28-ifndef(NO_UNUSED).
29-export([best/1, best/2, layout/1, layout/2, get_ctxt_paperwidth/1,
30	 set_ctxt_paperwidth/2, get_ctxt_linewidth/1,
31	 set_ctxt_linewidth/2, get_ctxt_hook/1, set_ctxt_hook/2,
32	 get_ctxt_user/1, set_ctxt_user/2]).
33-endif.
34
35-import(prettypr, [text/1, nest/2, above/2, beside/2, sep/1, par/1,
36		   par/2, follow/3, follow/2, floating/1, empty/0]).
37
38-import(cerl, [abstract/1, alias_pat/1, alias_var/1, apply_args/1,
39	       apply_op/1, atom_lit/1, binary_segments/1, bitstr_val/1,
40	       bitstr_size/1, bitstr_unit/1, bitstr_type/1,
41	       bitstr_flags/1, call_args/1, call_module/1, call_name/1,
42	       case_arg/1, case_clauses/1, catch_body/1, c_atom/1,
43	       c_binary/1, c_bitstr/5, c_int/1, clause_body/1,
44	       clause_guard/1, clause_pats/1, concrete/1, cons_hd/1,
45	       cons_tl/1, float_lit/1, fun_body/1, fun_vars/1,
46	       get_ann/1, int_lit/1, is_c_cons/1, is_c_let/1,
47	       is_c_nil/1, is_c_seq/1, is_print_string/1, let_arg/1,
48	       let_body/1, let_vars/1, letrec_body/1, letrec_defs/1,
49	       module_attrs/1, module_defs/1, module_exports/1,
50	       module_name/1, primop_args/1, primop_name/1,
51	       receive_action/1, receive_clauses/1, receive_timeout/1,
52	       seq_arg/1, seq_body/1, string_lit/1, try_arg/1,
53	       try_body/1, try_vars/1, try_evars/1, try_handler/1,
54	       tuple_es/1, type/1, values_es/1, var_name/1,
55	       map_arg/1, map_es/1, is_c_map_empty/1,
56	       map_pair_key/1, map_pair_val/1, map_pair_op/1
57	   ]).
58
59-define(PAPER, 76).
60-define(RIBBON, 45).
61-define(NOUSER, undefined).
62-define(NOHOOK, none).
63
64-type hook() :: 'none' | fun((cerl:cerl(), _, _) -> prettypr:document()).
65
66-record(ctxt, {line = 0         :: integer(),
67	       body_indent = 4  :: non_neg_integer(),
68	       sub_indent = 2   :: non_neg_integer(),
69	       hook = ?NOHOOK   :: hook(),
70	       noann = false    :: boolean(),
71	       paper = ?PAPER   :: integer(),
72	       ribbon = ?RIBBON :: integer(),
73	       user = ?NOUSER   :: term()}).
74-type context() :: #ctxt{}.
75
76%% =====================================================================
77%% The following functions examine and modify contexts:
78
79%% @spec (context()) -> integer()
80%% @doc Returns the paper widh field of the prettyprinter context.
81%% @see set_ctxt_paperwidth/2
82
83-ifndef(NO_UNUSED).
84get_ctxt_paperwidth(Ctxt) ->
85    Ctxt#ctxt.paper.
86-endif.	% NO_UNUSED
87%% @clear
88
89%% @spec (context(), integer()) -> context()
90%%
91%% @doc Updates the paper widh field of the prettyprinter context.
92%%
93%% <p> Note: changing this value (and passing the resulting context to a
94%% continuation function) does not affect the normal formatting, but may
95%% affect user-defined behaviour in hook functions.</p>
96%%
97%% @see get_ctxt_paperwidth/1
98
99-ifndef(NO_UNUSED).
100set_ctxt_paperwidth(Ctxt, W) ->
101    Ctxt#ctxt{paper = W}.
102-endif.	% NO_UNUSED
103%% @clear
104
105%% @spec (context()) -> integer()
106%% @doc Returns the line widh field of the prettyprinter context.
107%% @see set_ctxt_linewidth/2
108
109-ifndef(NO_UNUSED).
110get_ctxt_linewidth(Ctxt) ->
111    Ctxt#ctxt.ribbon.
112-endif.	% NO_UNUSED
113%% @clear
114
115%% @spec (context(), integer()) -> context()
116%%
117%% @doc Updates the line widh field of the prettyprinter context.
118%%
119%% <p> Note: changing this value (and passing the resulting context to a
120%% continuation function) does not affect the normal formatting, but may
121%% affect user-defined behaviour in hook functions.</p>
122%%
123%% @see get_ctxt_linewidth/1
124
125-ifndef(NO_UNUSED).
126set_ctxt_linewidth(Ctxt, W) ->
127    Ctxt#ctxt{ribbon = W}.
128-endif.	% NO_UNUSED
129%% @clear
130
131%% @spec (context()) -> hook()
132%% @doc Returns the hook function field of the prettyprinter context.
133%% @see set_ctxt_hook/2
134
135-ifndef(NO_UNUSED).
136get_ctxt_hook(Ctxt) ->
137    Ctxt#ctxt.hook.
138-endif.	% NO_UNUSED
139%% @clear
140
141%% @spec (context(), hook()) -> context()
142%% @doc Updates the hook function field of the prettyprinter context.
143%% @see get_ctxt_hook/1
144
145-ifndef(NO_UNUSED).
146set_ctxt_hook(Ctxt, Hook) ->
147    Ctxt#ctxt{hook = Hook}.
148-endif.	% NO_UNUSED
149%% @clear
150
151%% @spec (context()) -> term()
152%% @doc Returns the user data field of the prettyprinter context.
153%% @see set_ctxt_user/2
154
155-ifndef(NO_UNUSED).
156get_ctxt_user(Ctxt) ->
157    Ctxt#ctxt.user.
158-endif.	% NO_UNUSED
159%% @clear
160
161%% @spec (context(), term()) -> context()
162%% @doc Updates the user data field of the prettyprinter context.
163%% @see get_ctxt_user/1
164
165-ifndef(NO_UNUSED).
166set_ctxt_user(Ctxt, X) ->
167    Ctxt#ctxt{user = X}.
168-endif.	% NO_UNUSED
169%% @clear
170
171
172%% =====================================================================
173%% @spec format(Tree::cerl()) -> string()
174%% @equiv format(Tree, [])
175
176-spec format(cerl:cerl()) -> string().
177
178format(Node) ->
179    format(Node, []).
180
181
182%% =====================================================================
183%% @spec format(Tree::cerl(), Options::[term()]) -> string()
184%%           cerl() = cerl:cerl()
185%%
186%% @type hook() = (cerl(), context(), Continuation) -> document()
187%%	    Continuation = (cerl(), context()) -> document().
188%%
189%% A call-back function for user-controlled formatting. See <a
190%% href="#format-2"><code>format/2</code></a>.
191%%
192%% @type context(). A representation of the current context of the
193%% pretty-printer. Can be accessed in hook functions.
194%%
195%% @doc Prettyprint-formats a Core Erlang syntax tree as text.
196%%
197%% <p>Available options:
198%% <dl>
199%%   <dt>{hook, none | <a href="#type-hook">hook()</a>}</dt>
200%%       <dd>Unless the value is <code>none</code>, the given function
201%%       is called for every node; see below for details. The default
202%%       value is <code>none</code>.</dd>
203%%
204%%   <dt>{noann, boolean()}</dt>
205%%       <dd>If the value is <code>true</code>, annotations on the code
206%%       are not printed. The default value is <code>false</code>.</dd>
207%%
208%%   <dt>{paper, integer()}</dt>
209%%       <dd>Specifies the preferred maximum number of characters on any
210%%       line, including indentation. The default value is 76.</dd>
211%%
212%%   <dt>{ribbon, integer()}</dt>
213%%       <dd>Specifies the preferred maximum number of characters on any
214%%       line, not counting indentation. The default value is 45.</dd>
215%%
216%%   <dt>{user, term()}</dt>
217%%       <dd>User-specific data for use in hook functions. The default
218%%       value is <code>undefined</code>.</dd>
219%% </dl></p>
220%%
221%% <p>A hook function (cf. the <a
222%% href="#type-hook"><code>hook()</code></a> type) is passed the current
223%% syntax tree node, the context, and a continuation. The context can be
224%% examined and manipulated by functions such as
225%% <code>get_ctxt_user/1</code> and <code>set_ctxt_user/2</code>. The
226%% hook must return a "document" data structure (see
227%% <code>layout/2</code> and <code>best/2</code>); this may be
228%% constructed in part or in whole by applying the continuation
229%% function. For example, the following is a trivial hook:
230%% <pre>
231%%     fun (Node, Ctxt, Cont) -> Cont(Node, Ctxt) end
232%% </pre>
233%% which yields the same result as if no hook was given.
234%% The following, however:
235%% <pre>
236%%     fun (Node, Ctxt, Cont) ->
237%%         Doc = Cont(Node, Ctxt),
238%%         prettypr:beside(prettypr:text("&lt;b>"),
239%%                         prettypr:beside(Doc,
240%%                                         prettypr:text("&lt;/b>")))
241%%     end
242%% </pre>
243%% will place the text of any annotated node (regardless of the
244%% annotation data) between HTML "boldface begin" and "boldface end"
245%% tags. The function <code>annotate/3</code> is exported for use in
246%% hook functions.</p>
247%%
248%% @see cerl
249%% @see format/1
250%% @see layout/2
251%% @see best/2
252%% @see annotate/3
253%% @see get_ctxt_user/1
254%% @see set_ctxt_user/2
255
256-spec format(cerl:cerl(), [term()]) -> string().
257
258format(Node, Options) ->
259    W = proplists:get_value(paper, Options, ?PAPER),
260    L = proplists:get_value(ribbon, Options, ?RIBBON),
261    prettypr:format(layout(Node, Options), W, L).
262
263
264%% =====================================================================
265%% @spec best(Tree::cerl()) -> empty | document()
266%% @equiv best(Node, [])
267
268-ifndef(NO_UNUSED).
269best(Node) ->
270    best(Node, []).
271-endif.	% NO_UNUSED
272%% @clear
273
274
275%% =====================================================================
276%% @spec best(Tree::cerl(), Options::[term()]) ->
277%%           empty | document()
278%%
279%% @doc Creates a fixed "best" abstract layout for a Core Erlang syntax
280%% tree. This is similar to the <code>layout/2</code> function, except
281%% that here, the final layout has been selected with respect to the
282%% given options. The atom <code>empty</code> is returned if no such
283%% layout could be produced. For information on the options, see the
284%% <code>format/2</code> function.
285%%
286%% @see best/1
287%% @see layout/2
288%% @see format/2
289%% @see prettypr:best/2
290
291-ifndef(NO_UNUSED).
292best(Node, Options) ->
293    W = proplists:get_value(paper, Options, ?PAPER),
294    L = proplists:get_value(ribbon, Options, ?RIBBON),
295    prettypr:best(layout(Node, Options), W, L).
296-endif.	% NO_UNUSED
297%% @clear
298
299
300%% =====================================================================
301%% @spec layout(Tree::cerl()) -> document()
302%% @equiv layout(Tree, [])
303
304-ifndef(NO_UNUSED).
305layout(Node) ->
306    layout(Node, []).
307-endif.	% NO_UNUSED
308%% @clear
309
310
311%% =====================================================================
312%% @spec annotate(document(), Terms::[term()], context()) -> document()
313%%
314%% @doc Adds an annotation containing <code>Terms</code> around the
315%% given abstract document. This function is exported mainly for use in
316%% hook functions; see <code>format/2</code>.
317%%
318%% @see format/2
319
320-spec annotate(prettypr:document(), [term()], context()) -> prettypr:document().
321
322annotate(Doc, As0, Ctxt) ->
323    case strip_line(As0) of
324	[] ->
325	    Doc;
326	As ->
327	    case Ctxt#ctxt.noann of
328		false ->
329		    Es = seq(As, floating(text(",")), Ctxt,
330			     fun lay_concrete/2),
331		    follow(beside(floating(text("(")), Doc),
332			   beside(text("-| ["),
333				  beside(par(Es), floating(text("])")))),
334			   Ctxt#ctxt.sub_indent);
335		true ->
336		    Doc
337	    end
338    end.
339
340
341%% =====================================================================
342%% @spec layout(Tree::cerl(), Options::[term()]) -> document()
343%%	    document() = prettypr:document()
344%%
345%% @doc Creates an abstract document layout for a syntax tree. The
346%% result represents a set of possible layouts (cf. module
347%% <code>prettypr</code>). For information on the options, see
348%% <code>format/2</code>; note, however, that the <code>paper</code> and
349%% <code>ribbon</code> options are ignored by this function.
350%%
351%% <p>This function provides a low-level interface to the pretty
352%% printer, returning a flexible representation of possible layouts,
353%% independent of the paper width eventually to be used for formatting.
354%% This can be included as part of another document and/or further
355%% processed directly by the functions in the <code>prettypr</code>
356%% module, or used in a hook function (see <code>format/2</code> for
357%% details).</p>
358%%
359%% @see prettypr
360%% @see format/2
361%% @see layout/1
362
363-spec layout(cerl:cerl(), [term()]) -> prettypr:document().
364
365layout(Node, Options) ->
366    lay(Node,
367	#ctxt{hook = proplists:get_value(hook, Options, ?NOHOOK),
368	      noann = proplists:get_bool(noann, Options),
369	      paper = proplists:get_value(paper, Options, ?PAPER),
370	      ribbon = proplists:get_value(ribbon, Options, ?RIBBON),
371	      user = proplists:get_value(user, Options)}).
372
373lay(Node, Ctxt) ->
374    case get_line(get_ann(Node)) of
375	none ->
376	    lay_0(Node, Ctxt);
377	Line ->
378	    if Line > Ctxt#ctxt.line ->
379		    Ctxt1 = Ctxt#ctxt{line = Line},
380		    Txt = io_lib:format("% Line ~w",[Line]),
381%		    beside(lay_0(Node, Ctxt1), floating(text(Txt)));
382		    above(floating(text(Txt)), lay_0(Node, Ctxt1));
383	       true ->
384		    lay_0(Node, Ctxt)
385	    end
386    end.
387
388lay_0(Node, Ctxt) ->
389    case Ctxt#ctxt.hook of
390	?NOHOOK ->
391	    lay_ann(Node, Ctxt);
392	Hook ->
393	    %% If there is a hook, we apply it.
394	    Hook(Node, Ctxt, fun lay_ann/2)
395    end.
396
397%% This adds an annotation list (if nonempty) around a document, unless
398%% the `noann' option is enabled.
399
400lay_ann(Node, Ctxt) ->
401    Doc = lay_1(Node, Ctxt),
402    As = get_ann(Node),
403    annotate(Doc, As, Ctxt).
404
405%% This part ignores annotations:
406
407lay_1(Node, Ctxt) ->
408    case type(Node) of
409	literal ->
410	    lay_literal(Node, Ctxt);
411	var ->
412	    lay_var(Node, Ctxt);
413	values ->
414	    lay_values(Node, Ctxt);
415	cons ->
416	    lay_cons(Node, Ctxt);
417	tuple ->
418	    lay_tuple(Node, Ctxt);
419	map ->
420	    lay_map(Node, Ctxt);
421	map_pair ->
422	    lay_map_pair(Node, Ctxt);
423	'let' ->
424	    lay_let(Node, Ctxt);
425	seq ->
426	    lay_seq(Node, Ctxt);
427	apply ->
428	    lay_apply(Node, Ctxt);
429	call ->
430	    lay_call(Node, Ctxt);
431	primop ->
432	    lay_primop(Node, Ctxt);
433	'case' ->
434	    lay_case(Node, Ctxt);
435	clause ->
436	    lay_clause(Node, Ctxt);
437	alias ->
438	    lay_alias(Node, Ctxt);
439	'fun' ->
440	    lay_fun(Node, Ctxt);
441	'receive' ->
442	    lay_receive(Node, Ctxt);
443	'try' ->
444	    lay_try(Node, Ctxt);
445	'catch' ->
446	    lay_catch(Node, Ctxt);
447	letrec ->
448	    lay_letrec(Node, Ctxt);
449	module ->
450	    lay_module(Node, Ctxt);
451	binary ->
452	    lay_binary(Node, Ctxt);
453	bitstr ->
454	    lay_bitstr(Node, Ctxt)
455    end.
456
457lay_literal(Node, Ctxt) ->
458    case concrete(Node) of
459	V when is_atom(V) ->
460	    text(atom_lit(Node));
461	V when is_float(V) ->
462	    text(tidy_float(float_lit(Node)));
463	V when is_integer(V) ->
464	    %% Note that we do not even try to recognize values
465	    %% that could represent printable characters - we
466	    %% always print an integer.
467	    text(int_lit(Node));
468        V when is_bitstring(V) ->
469            Val = fun(I) when is_integer(I) -> I;
470                     (B) when is_bitstring(B) ->
471                          BZ = bit_size(B), <<BV:BZ>> = B, BV
472                  end,
473            Sz = fun(I) when is_integer(I) -> 8;
474                    (B) when is_bitstring(B) -> bit_size(B)
475                 end,
476	    lay_binary(c_binary([c_bitstr(abstract(Val(B)),
477					  abstract(Sz(B)),
478					  abstract(1),
479					  abstract(integer),
480					  abstract([unsigned, big]))
481				 || B <- bitstring_to_list(V)]),
482		       Ctxt);
483	[] ->
484	    text("[]");
485	[_ | _] ->
486	    %% `lay_cons' will check for strings.
487	    lay_cons(Node, Ctxt);
488	V when is_tuple(V) ->
489	    lay_tuple(Node, Ctxt);
490	M when is_map(M) ->
491            lay_map(Node, Ctxt)
492    end.
493
494lay_var(Node, Ctxt) ->
495    %% When formatting variable names, no two names should ever map to
496    %% the same string. We assume below that an atom representing a
497    %% variable name either has the character sequence of a proper
498    %% variable, or otherwise does not need single-quoting.
499    case var_name(Node) of
500	V when is_atom(V) ->
501	    S = atom_to_list(V),
502	    case S of
503		[C | _] when C >= $A, C =< $Z ->
504		    %% Ordinary uppercase-prefixed names are printed
505		    %% just as they are.
506		    text(S);
507		[C | _] when C >= $\300, C =< $\336, C /= $\327 ->
508		    %% These are also uppercase (ISO 8859-1).
509		    text(S);
510		[$_| _] ->
511		    %% If the name starts with '_' we keep the name as is.
512		    text(S);
513		_ ->
514		    %% Plain atom names are prefixed with a single "_".
515		    %% E.g. 'foo' => "_foo".
516		    text([$_ | S])
517	    end;
518	V when is_integer(V) ->
519	    %% Integers are always simply prefixed with "_";
520	    %% e.g. 4711 => "_4711".
521	    text([$_ | integer_to_list(V)]);
522	{N, A} when is_atom(N), is_integer(A) ->
523	    %% Function names have no overlap problem.
524	    beside(lay_noann(c_atom(atom_to_list(N)), Ctxt),
525		   beside(text("/"), lay_noann(c_int(A), Ctxt)))
526    end.
527
528lay_values(Node, Ctxt) ->
529    lay_value_list(values_es(Node), Ctxt).
530
531lay_cons(Node, Ctxt) ->
532    case is_print_string(Node) of
533	true ->
534	    lay_string(string_lit(Node), Ctxt);
535	false ->
536	    beside(floating(text("[")),
537		   beside(par(lay_list_elements(Node, Ctxt)),
538			  floating(text("]"))))
539    end.
540
541lay_string(S, Ctxt) ->
542    %% S includes leading/trailing double-quote characters. The segment
543    %% width is 2/3 of the ribbon width - this seems to work well.
544    W = (Ctxt#ctxt.ribbon) * 2 div 3,
545    lay_string_1(S, length(S), W).
546
547lay_string_1(S, L, W) when L > W, W > 0 ->
548    %% Note that L is the minimum, not the exact, printed length.
549    case split_string(S, W - 1, L) of
550	{_, ""} ->
551	    text(S);
552	{S1, S2} ->
553	    above(text(S1 ++ "\""),
554		  lay_string_1([$" | S2], L - W + 1, W))
555    end;
556lay_string_1(S, _L, _W) ->
557    text(S).
558
559split_string(Xs, N, L) ->
560    split_string_1(Xs, N, L, []).
561
562%% We only split strings at whitespace, if possible. We must make sure
563%% we do not split an escape sequence.
564
565split_string_1([$\s | Xs], N, L, As) when N =< 0, L >= 5 ->
566    {lists:reverse([$\s | As]), Xs};
567split_string_1([$\t | Xs], N, L, As) when N =< 0, L >= 5 ->
568    {lists:reverse([$t, $\\ | As]), Xs};
569split_string_1([$\n | Xs], N, L, As) when N =< 0, L >= 5 ->
570    {lists:reverse([$n, $\\ | As]), Xs};
571split_string_1([$\\ | Xs], N, L, As) ->
572    split_string_2(Xs, N - 1, L - 1, [$\\ | As]);
573split_string_1(Xs, N, L, As) when N =< -10, L >= 5 ->
574    {lists:reverse(As), Xs};
575split_string_1([X | Xs], N, L, As) ->
576    split_string_1(Xs, N - 1, L - 1, [X | As]);
577split_string_1([], _N, _L, As) ->
578    {lists:reverse(As), ""}.
579
580split_string_2([$^, X | Xs], N, L, As) ->
581    split_string_1(Xs, N - 2, L - 2, [X, $^ | As]);
582split_string_2([X1, X2, X3 | Xs], N, L, As) when
583  X1 >= $0, X1 =< $7, X2 >= $0, X2 =< $7, X3 >= $0, X3 =< $7 ->
584    split_string_1(Xs, N - 3, L - 3, [X3, X2, X1 | As]);
585split_string_2([X1, X2 | Xs], N, L, As) when
586  X1 >= $0, X1 =< $7, X2 >= $0, X2 =< $7 ->
587    split_string_1(Xs, N - 2, L - 2, [X2, X1 | As]);
588split_string_2([X | Xs], N, L, As) ->
589    split_string_1(Xs, N - 1, L - 1, [X | As]).
590
591lay_tuple(Node, Ctxt) ->
592    beside(floating(text("{")),
593	   beside(par(seq(tuple_es(Node), floating(text(",")),
594			  Ctxt, fun lay/2)),
595		  floating(text("}")))).
596
597lay_map(Node, Ctxt) ->
598    Arg = map_arg(Node),
599    After = case is_c_map_empty(Arg) of
600	true -> floating(text("}~"));
601	false ->
602	    beside(floating(text(" | ")),
603		beside(lay(Arg,Ctxt),
604		    floating(text("}~"))))
605    end,
606    beside(floating(text("~{")),
607        beside(par(seq(map_es(Node), floating(text(",")), Ctxt, fun lay/2)),
608	    After)).
609
610lay_map_pair(Node, Ctxt) ->
611    K = map_pair_key(Node),
612    V = map_pair_val(Node),
613    OpTxt = case concrete(map_pair_op(Node)) of
614	assoc -> "=>";
615	exact -> ":="
616    end,
617    beside(lay(K,Ctxt),beside(floating(text(OpTxt)),lay(V,Ctxt))).
618
619lay_let(Node, Ctxt) ->
620    V = lay_value_list(let_vars(Node), Ctxt),
621    D1 = par([follow(text("let"),
622		     beside(V, floating(text(" ="))),
623		     Ctxt#ctxt.sub_indent),
624	      lay(let_arg(Node), Ctxt)],
625	     Ctxt#ctxt.body_indent),
626    B = let_body(Node),
627    D2 = lay(B, Ctxt),
628    case is_c_let(B) of
629	true ->
630	    sep([beside(D1, floating(text(" in"))), D2]);
631	false ->
632	    sep([D1, beside(text("in "), D2)])
633    end.
634
635lay_seq(Node, Ctxt) ->
636    D1 = beside(text("do "), lay(seq_arg(Node), Ctxt)),
637    B = seq_body(Node),
638    D2 = lay(B, Ctxt),
639    case is_c_seq(B) of
640	true ->
641	    sep([D1, D2]);
642	false ->
643	    sep([D1, nest(3, D2)])
644    end.
645
646lay_apply(Node, Ctxt) ->
647    As = seq(apply_args(Node), floating(text(",")), Ctxt,
648	     fun lay/2),
649    beside(follow(text("apply"), lay(apply_op(Node), Ctxt)),
650	   beside(text("("),
651		  beside(par(As), floating(text(")"))))).
652
653lay_call(Node, Ctxt) ->
654    As = seq(call_args(Node), floating(text(",")), Ctxt,
655	     fun lay/2),
656    beside(follow(text("call"),
657		  beside(beside(lay(call_module(Node), Ctxt),
658				floating(text(":"))),
659			 lay(call_name(Node), Ctxt)),
660		  Ctxt#ctxt.sub_indent),
661	   beside(text("("), beside(par(As),
662				    floating(text(")"))))).
663
664lay_primop(Node, Ctxt) ->
665    As = seq(primop_args(Node), floating(text(",")), Ctxt,
666	     fun lay/2),
667    beside(follow(text("primop"),
668		  lay(primop_name(Node), Ctxt),
669		  Ctxt#ctxt.sub_indent),
670	   beside(text("("), beside(par(As),
671				    floating(text(")"))))).
672
673lay_case(Node, Ctxt) ->
674    Cs = seq(case_clauses(Node), none, Ctxt, fun lay/2),
675    sep([par([follow(text("case"),
676		     lay(case_arg(Node), Ctxt),
677		     Ctxt#ctxt.sub_indent),
678	      text("of")],
679	     Ctxt#ctxt.sub_indent),
680	 nest(Ctxt#ctxt.sub_indent,
681	      vertical(Cs)),
682	 text("end")]).
683
684lay_clause(Node, Ctxt) ->
685    P = lay_value_list(clause_pats(Node), Ctxt),
686    G = lay(clause_guard(Node), Ctxt),
687    H = par([P, follow(follow(text("when"), G,
688			      Ctxt#ctxt.sub_indent),
689		       floating(text("->")))],
690	    Ctxt#ctxt.sub_indent),
691    par([H, lay(clause_body(Node), Ctxt)],
692	Ctxt#ctxt.body_indent).
693
694lay_alias(Node, Ctxt) ->
695    follow(beside(lay(alias_var(Node), Ctxt),
696		  text(" =")),
697	   lay(alias_pat(Node), Ctxt),
698	   Ctxt#ctxt.body_indent).
699
700lay_fun(Node, Ctxt) ->
701    Vs = seq(fun_vars(Node), floating(text(",")),
702	     Ctxt, fun lay/2),
703    par([follow(text("fun"),
704		beside(text("("),
705		       beside(par(Vs),
706			      floating(text(") ->")))),
707		Ctxt#ctxt.sub_indent),
708	 lay(fun_body(Node), Ctxt)],
709	Ctxt#ctxt.body_indent).
710
711lay_receive(Node, Ctxt) ->
712    Cs = seq(receive_clauses(Node), none, Ctxt, fun lay/2),
713    sep([text("receive"),
714	 nest(Ctxt#ctxt.sub_indent, vertical(Cs)),
715	 sep([follow(text("after"),
716		     beside(lay(receive_timeout(Node), Ctxt),
717			    floating(text(" ->"))),
718		     Ctxt#ctxt.sub_indent),
719	      nest(Ctxt#ctxt.sub_indent,
720		   lay(receive_action(Node), Ctxt))])]).
721
722lay_try(Node, Ctxt) ->
723    Vs = lay_value_list(try_vars(Node), Ctxt),
724    Evs = lay_value_list(try_evars(Node), Ctxt),
725    sep([follow(text("try"),
726		lay(try_arg(Node), Ctxt),
727		Ctxt#ctxt.body_indent),
728	 follow(beside(beside(text("of "), Vs),
729		       floating(text(" ->"))),
730		lay(try_body(Node), Ctxt),
731		Ctxt#ctxt.body_indent),
732	 follow(beside(beside(text("catch "), Evs),
733		       floating(text(" ->"))),
734		lay(try_handler(Node), Ctxt),
735		Ctxt#ctxt.body_indent)]).
736
737lay_catch(Node, Ctxt) ->
738    follow(text("catch"),
739	   lay(catch_body(Node), Ctxt),
740	   Ctxt#ctxt.sub_indent).
741
742lay_letrec(Node, Ctxt) ->
743    Es = seq(letrec_defs(Node), none, Ctxt, fun lay_fdef/2),
744    sep([text("letrec"),
745	 nest(Ctxt#ctxt.sub_indent, vertical(Es)),
746	 beside(text("in "), lay(letrec_body(Node), Ctxt))]).
747
748lay_module(Node, Ctxt) ->
749    %% Note that the module name, exports and attributes may not
750    %% be annotated in the printed format.
751    Xs = seq(module_exports(Node), floating(text(",")), Ctxt,
752	     fun lay_noann/2),
753    As = seq(module_attrs(Node), floating(text(",")), Ctxt,
754	     fun lay_attrdef/2),
755    Es = seq(module_defs(Node), none, Ctxt, fun lay_fdef/2),
756    sep([follow(text("module"),
757		follow(lay_noann(module_name(Node), Ctxt),
758		       beside(beside(text("["), par(Xs)),
759			      floating(text("]")))),
760		Ctxt#ctxt.sub_indent),
761	 nest(Ctxt#ctxt.sub_indent,
762	      follow(text("attributes"),
763		     beside(beside(text("["), par(As)),
764			    floating(text("]"))),
765		     Ctxt#ctxt.sub_indent)),
766	 nest(Ctxt#ctxt.sub_indent, vertical(Es)),
767	 text("end")]).
768
769lay_binary(Node, Ctxt) ->
770    beside(floating(text("#{")),
771	   beside(sep(seq(binary_segments(Node), floating(text(",")),
772			  Ctxt, fun lay_bitstr/2)),
773		  floating(text("}#")))).
774
775lay_bitstr(Node, Ctxt) ->
776    Head = beside(floating(text("#<")),
777		  beside(lay(bitstr_val(Node), Ctxt),
778			 floating(text(">")))),
779    As = [bitstr_size(Node),
780	  bitstr_unit(Node),
781	  bitstr_type(Node),
782	  bitstr_flags(Node)],
783    beside(Head, beside(floating(text("(")),
784			beside(sep(seq(As, floating(text(",")),
785				       Ctxt, fun lay/2)),
786			       floating(text(")"))))).
787
788%% In all places where "<...>"-sequences can occur, it is OK to
789%% write 1-element sequences without the "<" and ">".
790
791lay_value_list([E], Ctxt) ->
792    lay(E, Ctxt);
793lay_value_list(Es, Ctxt) ->
794    beside(floating(text("<")),
795	   beside(par(seq(Es, floating(text(",")),
796			  Ctxt, fun lay/2)),
797		  floating(text(">")))).
798
799lay_noann(Node, Ctxt) ->
800    lay(Node, Ctxt#ctxt{noann = true}).
801
802lay_concrete(T, Ctxt) ->
803    lay(abstract(T), Ctxt).
804
805lay_attrdef({K, V}, Ctxt) ->
806    follow(beside(lay_noann(K, Ctxt), floating(text(" ="))),
807	   lay_noann(V, Ctxt),
808	   Ctxt#ctxt.body_indent).
809
810lay_fdef({N, F}, Ctxt) ->
811    par([beside(lay(N, Ctxt), floating(text(" ="))),
812	 lay(F, Ctxt)],
813	Ctxt#ctxt.body_indent).
814
815lay_list_elements(Node, Ctxt) ->
816    T = cons_tl(Node),
817    A = case Ctxt#ctxt.noann of
818	    false ->
819		get_ann(T);
820	    true ->
821		[]
822	end,
823    H = lay(cons_hd(Node), Ctxt),
824    case is_c_cons(T) of
825	true when A =:= [] ->
826	    [beside(H, floating(text(",")))
827	     | lay_list_elements(T, Ctxt)];
828	_ ->
829	    case is_c_nil(T) of
830		true when A =:= [] ->
831		    [H];
832		_ ->
833		    [H, beside(floating(text("| ")),
834			       lay(T, Ctxt))]
835	    end
836    end.
837
838seq([H | T], Separator, Ctxt, Fun) ->
839    case T of
840	[] ->
841	    [Fun(H, Ctxt)];
842	_ ->
843	    [maybe_append(Separator, Fun(H, Ctxt))
844	     | seq(T, Separator, Ctxt, Fun)]
845    end;
846seq([], _, _, _) ->
847    [empty()].
848
849maybe_append(none, D) ->
850    D;
851maybe_append(Suffix, D) ->
852    beside(D, Suffix).
853
854vertical([D]) ->
855    D;
856vertical([D | Ds]) ->
857    above(D, vertical(Ds));
858vertical([]) ->
859    [].
860
861% horizontal([D]) ->
862%     D;
863% horizontal([D | Ds]) ->
864%     beside(D, horizontal(Ds));
865% horizontal([]) ->
866%     [].
867
868tidy_float([$., C | Cs]) ->
869    [$., C | tidy_float_1(Cs)];  % preserve first decimal digit
870tidy_float([$e | _] = Cs) ->
871    tidy_float_2(Cs);
872tidy_float([C | Cs]) ->
873    [C | tidy_float(Cs)];
874tidy_float([]) ->
875    [].
876
877tidy_float_1([$0, $0, $0 | Cs]) ->
878    tidy_float_2(Cs);    % cut mantissa at three consecutive zeros.
879tidy_float_1([$e | _] = Cs) ->
880    tidy_float_2(Cs);
881tidy_float_1([C | Cs]) ->
882    [C | tidy_float_1(Cs)];
883tidy_float_1([]) ->
884    [].
885
886tidy_float_2([$e, $+, $0]) -> [];
887tidy_float_2([$e, $+, $0 | Cs]) -> tidy_float_2([$e, $+ | Cs]);
888tidy_float_2([$e, $+ | _] = Cs) -> Cs;
889tidy_float_2([$e, $-, $0]) -> [];
890tidy_float_2([$e, $-, $0 | Cs]) -> tidy_float_2([$e, $- | Cs]);
891tidy_float_2([$e, $- | _] = Cs) -> Cs;
892tidy_float_2([$e | Cs]) -> tidy_float_2([$e, $+ | Cs]);
893tidy_float_2([_ | Cs]) -> tidy_float_2(Cs);
894tidy_float_2([]) -> [].
895
896get_line([L | _As]) when is_integer(L) ->
897    L;
898get_line([{L, _Column} | _As]) when is_integer(L) ->
899    L;
900get_line([_ | As]) ->
901    get_line(As);
902get_line([]) ->
903    none.
904
905strip_line([A | As]) when is_integer(A) ->
906    strip_line(As);
907strip_line([A | As]) ->
908    [A | strip_line(As)];
909strip_line([]) ->
910    [].
911
912%% =====================================================================
913