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("<b>"), 239%% prettypr:beside(Doc, 240%% prettypr:text("</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