1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1999-2018. 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%% Purpose : Core Erlang (naive) prettyprinter
21
22-module(core_pp).
23
24-export([format/1,format_all/1]).
25
26-include("core_parse.hrl").
27
28%% ====================================================================== %%
29%% format(Node) -> Text
30%%	Node = coreErlang()
31%%	Text = string() | [Text]
32%%
33%%	Prettyprint-formats (naively) an abstract Core Erlang syntax
34%%	tree.
35
36-record(ctxt, {indent = 0      :: integer(),
37	       item_indent = 2 :: integer(),
38	       body_indent = 4 :: integer(),
39	       line = 0        :: integer(),
40	       clean = true    :: boolean()}).
41
42-define(TAB_WIDTH, 8).
43
44-spec format(cerl:cerl()) -> iolist().
45
46format(Node) ->
47    format(Node, #ctxt{}).
48
49-spec format_all(cerl:cerl()) -> iolist().
50
51format_all(Node) ->
52    format(Node, #ctxt{clean=false}).
53
54maybe_anno(Node, Fun, #ctxt{clean=false}=Ctxt) ->
55    As = cerl:get_ann(Node),
56    maybe_anno(Node, Fun, Ctxt, As);
57maybe_anno(Node, Fun, #ctxt{clean=true}=Ctxt) ->
58    As0 = cerl:get_ann(Node),
59    case get_line(As0) of
60	none ->
61	    maybe_anno(Node, Fun, Ctxt, As0);
62  	Line ->
63	    As = strip_line(As0),
64	    if Line > Ctxt#ctxt.line ->
65		    [io_lib:format("%% Line ~w",[Line]),
66		     nl_indent(Ctxt),
67		     maybe_anno(Node, Fun, Ctxt#ctxt{line = Line}, As)
68		    ];
69		true ->
70		    maybe_anno(Node, Fun, Ctxt, As)
71	    end
72    end.
73
74maybe_anno(Node, Fun, Ctxt, []) ->
75    Fun(Node, Ctxt);
76maybe_anno(Node, Fun, Ctxt, List) ->
77    Ctxt1 = add_indent(Ctxt, 2),
78    Ctxt2 = add_indent(Ctxt1, 3),
79    ["( ",
80     Fun(Node, Ctxt1),
81     nl_indent(Ctxt1),
82     "-| ",format_anno(List, Ctxt2)," )"
83    ].
84
85format_anno([_|_]=List, Ctxt) ->
86    [$[,format_anno_list(List, Ctxt),$]];
87format_anno({file,Name}, _Ctxt) ->
88    %% Optimization: Reduces file size considerably.
89    io_lib:format("{'file',~p}", [Name]);
90format_anno(Tuple, Ctxt) when is_tuple(Tuple) ->
91    [${,format_anno_list(tuple_to_list(Tuple), Ctxt),$}];
92format_anno(Val, Ctxt) when is_atom(Val) ->
93    format_1(#c_literal{val=Val}, Ctxt);
94format_anno(Val, Ctxt) when is_integer(Val) ->
95    format_1(#c_literal{val=Val}, Ctxt).
96
97format_anno_list([H|[_|_]=T], Ctxt) ->
98    [format_anno(H, Ctxt), $, | format_anno_list(T, Ctxt)];
99format_anno_list([H], Ctxt) ->
100    format_anno(H, Ctxt).
101
102strip_line([A | As]) when is_integer(A) ->
103    strip_line(As);
104strip_line([{A,C} | As]) when is_integer(A), is_integer(C) ->
105    strip_line(As);
106strip_line([{file,_File} | As]) ->
107    strip_line(As);
108strip_line([A | As]) ->
109    [A | strip_line(As)];
110strip_line([]) ->
111    [].
112
113get_line([L | _As]) when is_integer(L) ->
114    L;
115get_line([{L, _Column} | _As]) when is_integer(L) ->
116    L;
117get_line([_ | As]) ->
118    get_line(As);
119get_line([]) ->
120    none.
121
122format(Node, Ctxt) ->
123    maybe_anno(Node, fun format_1/2, Ctxt).
124
125format_1(#c_literal{val=[]}, _) -> "[]";
126format_1(#c_literal{val=I}, _) when is_integer(I) -> integer_to_list(I);
127format_1(#c_literal{val=F}, _) when is_float(F) -> float_to_list(F);
128format_1(#c_literal{val=A}, _) when is_atom(A) -> core_atom(A);
129format_1(#c_literal{val=[H|T]}, Ctxt) ->
130    format_1(#c_cons{hd=#c_literal{val=H},tl=#c_literal{val=T}}, Ctxt);
131format_1(#c_literal{val=Tuple}, Ctxt) when is_tuple(Tuple) ->
132    format_1(#c_tuple{es=[#c_literal{val=E} || E <- tuple_to_list(Tuple)]}, Ctxt);
133format_1(#c_literal{anno=A,val=Bitstring}, Ctxt) when is_bitstring(Bitstring) ->
134    Segs = segs_from_bitstring(Bitstring),
135    format_1(#c_binary{anno=A,segments=Segs}, Ctxt);
136format_1(#c_literal{anno=A,val=M},Ctxt) when is_map(M) ->
137    Pairs = maps:to_list(M),
138    Op = #c_literal{val=assoc},
139    Cpairs = [#c_map_pair{op=Op,
140			  key=#c_literal{val=K},
141			  val=#c_literal{val=V}} || {K,V} <- Pairs],
142    format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt);
143format_1(#c_literal{val=F},_Ctxt) when is_function(F) ->
144    {module,M} = erlang:fun_info(F, module),
145    {name,N} = erlang:fun_info(F, name),
146    {arity,A} = erlang:fun_info(F, arity),
147    ["fun ",core_atom(M),$:,core_atom(N),$/,integer_to_list(A)];
148format_1(#c_var{name={I,A}}, _) ->
149    [core_atom(I),$/,integer_to_list(A)];
150format_1(#c_var{name=V}, _) ->
151    %% Internal variable names may be:
152    %%     - atoms representing proper Erlang variable names, or
153    %%       any atoms that may be printed without single-quoting
154    %%     - nonnegative integers.
155    %% It is important that when printing variables, no two names
156    %% should ever map to the same string.
157    if is_atom(V) ->
158	    S = atom_to_list(V),
159	    case S of
160		[C | _] when C >= $A, C =< $Z ->
161		    %% Ordinary uppercase-prefixed names are
162		    %% printed just as they are.
163		    S;
164		[$_ | _] ->
165		    %% Already "_"-prefixed names are prefixed
166		    %% with "_X", e.g. '_foo' => '_X_foo', to
167		    %% avoid generating things like "____foo" upon
168		    %% repeated writing and reading of code.
169		    %% ("_X_X_X_foo" is better.)
170		    [$_, $X | S];
171		_ ->
172		    %% Plain atoms are prefixed with a single "_".
173		    %% E.g. foo => "_foo".
174		    [$_ | S]
175	    end;
176       is_integer(V) ->
177	    %% Integers are also simply prefixed with "_".
178	    [$_ | integer_to_list(V)]
179    end;
180format_1(#c_binary{segments=Segs}, Ctxt) ->
181    ["#{",
182     format_vseq(Segs, "", ",", add_indent(Ctxt, 2),
183		 fun format_bitstr/2),
184     "}#"
185    ];
186format_1(#c_tuple{es=Es}, Ctxt) ->
187    [${,
188     format_hseq(Es, ",", add_indent(Ctxt, 1), fun format/2),
189     $}
190    ];
191format_1(#c_map{arg=#c_literal{val=M},es=Es}, Ctxt)
192  when is_map(M), map_size(M) =:= 0 ->
193    ["~{",
194     format_hseq(Es, ",", add_indent(Ctxt, 1), fun format/2),
195     "}~"
196    ];
197format_1(#c_map{arg=Var,es=Es}, Ctxt) ->
198    ["~{",
199     format_hseq(Es, ",", add_indent(Ctxt, 1), fun format/2),
200     "|",format(Var, add_indent(Ctxt, 1)),
201     "}~"
202    ];
203format_1(#c_map_pair{op=#c_literal{val=assoc},key=K,val=V}, Ctxt) ->
204    format_map_pair("=>", K, V, Ctxt);
205format_1(#c_map_pair{op=#c_literal{val=exact},key=K,val=V}, Ctxt) ->
206    format_map_pair(":=", K, V, Ctxt);
207format_1(#c_cons{hd=H,tl=T}, Ctxt) ->
208    Txt = ["["|format(H, add_indent(Ctxt, 1))],
209    [Txt|format_list_tail(T, add_indent(Ctxt, width(Txt, Ctxt)))];
210format_1(#c_values{es=Es}, Ctxt) ->
211    format_values(Es, Ctxt);
212format_1(#c_alias{var=V,pat=P}, Ctxt) ->
213    Txt = [format(V, Ctxt)|" = "],
214    [Txt|format(P, add_indent(Ctxt, width(Txt, Ctxt)))];
215format_1(#c_let{anno=Anno0,vars=Vs0,arg=A0,body=B}, #ctxt{clean=Clean}=Ctxt) ->
216    {Vs,A,Anno} = case Clean of
217		      false ->
218			  {Vs0,A0,Anno0};
219		      true ->
220			  {[cerl:set_ann(V, []) || V <- Vs0],
221			   clean_anno_carefully(A0),
222			   []}
223		  end,
224    case is_simple_term(A) andalso Anno =:= [] of
225	false ->
226	    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
227	    ["let ",
228	     format_values(Vs, add_indent(Ctxt, 4)),
229	     " =",
230	     nl_indent(Ctxt1),
231	     format(A, Ctxt1),
232	     nl_indent(Ctxt),
233	     "in  "
234	     | format(B, add_indent(Ctxt, 4))
235	    ];
236	true ->
237	    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
238	    ["let ",
239	     format_values(Vs, add_indent(Ctxt, 4)),
240	     " = ",
241	     format(A, Ctxt1),
242	     nl_indent(Ctxt),
243	     "in  "
244	     | format(B, add_indent(Ctxt, 4))
245	    ]
246    end;
247format_1(#c_letrec{defs=Fs,body=B}, Ctxt) ->
248    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
249    ["letrec",
250     nl_indent(Ctxt1),
251     format_funcs(Fs, Ctxt1),
252     nl_indent(Ctxt),
253     "in  "
254     | format(B, add_indent(Ctxt, 4))
255    ];
256format_1(#c_seq{arg=A,body=B}, Ctxt) ->
257    Ctxt1 = add_indent(Ctxt, 4),
258    ["do  ",
259     format(A, Ctxt1),
260     nl_indent(Ctxt1)
261     | format(B, Ctxt1)
262    ];
263format_1(#c_case{arg=A,clauses=Cs}, Ctxt) ->
264    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
265    ["case ",
266     format(A, add_indent(Ctxt, 5)),
267     " of",
268     nl_indent(Ctxt1),
269     format_clauses(Cs, Ctxt1),
270     nl_indent(Ctxt)
271     | "end"
272    ];
273format_1(#c_receive{clauses=Cs,timeout=T,action=A}, Ctxt) ->
274    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
275    ["receive",
276     nl_indent(Ctxt1),
277     format_clauses(Cs, Ctxt1),
278     nl_indent(Ctxt),
279     "after ",
280     format(T, add_indent(Ctxt, 6)),
281     " ->",
282     nl_indent(Ctxt1),
283     format(A, Ctxt1)
284    ];
285format_1(#c_fun{vars=Vs,body=B}, Ctxt) ->
286    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
287    ["fun (",
288     format_hseq(Vs, ",", add_indent(Ctxt, 5), fun format/2),
289     ") ->",
290     nl_indent(Ctxt1)
291     | format(B, Ctxt1)
292    ];
293format_1(#c_apply{op=O,args=As}, Ctxt0) ->
294    Ctxt1 = add_indent(Ctxt0, 6),		%"apply "
295    Op = format(O, Ctxt1),
296    Ctxt2 = add_indent(Ctxt0, 4),
297    ["apply ",Op,
298     nl_indent(Ctxt2),
299     $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
300    ];
301format_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
302    Ctxt1 = add_indent(Ctxt0, 5),		%"call "
303    Mod = format(M, Ctxt1),
304    Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
305    Name = format(N, Ctxt2),
306    Ctxt3 = add_indent(Ctxt0, 4),
307    ["call ",Mod,":",Name,
308     nl_indent(Ctxt3),
309     $(,format_hseq(As, ", ", add_indent(Ctxt3, 1), fun format/2),$)
310    ];
311format_1(#c_primop{name=N,args=As}, Ctxt0) ->
312    Ctxt1 = add_indent(Ctxt0, 7),		%"primop "
313    Name = format(N, Ctxt1),
314    Ctxt2 = add_indent(Ctxt0, 4),
315    ["primop ",Name,
316     nl_indent(Ctxt2),
317     $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
318    ];
319format_1(#c_catch{body=B}, Ctxt) ->
320    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
321    ["catch",
322     nl_indent(Ctxt1),
323     format(B, Ctxt1)
324    ];
325format_1(#c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
326    Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
327    ["try",
328     nl_indent(Ctxt1),
329     format(E, Ctxt1),
330     nl_indent(Ctxt),
331     "of ",
332     format_values(Vs, add_indent(Ctxt, 3)),
333     " ->",
334     nl_indent(Ctxt1),
335     format(B, Ctxt1),
336     nl_indent(Ctxt),
337     "catch ",
338     format_values(Evs, add_indent(Ctxt, 6)),
339     " ->",
340     nl_indent(Ctxt1)
341     | format(H, Ctxt1)
342    ];
343format_1(#c_module{name=N,exports=Es,attrs=As,defs=Ds}, Ctxt) ->
344    Mod = ["module ", format(N, Ctxt)],
345    [Mod," [",
346     format_vseq(Es,
347		 "", ",",
348		 add_indent(Ctxt, width(Mod, Ctxt)+2),
349		 fun format/2),
350     "]",
351     nl_indent(Ctxt),
352     "    attributes [",
353     format_vseq(As,
354		 "", ",",
355		 add_indent(Ctxt, 16),
356		 fun format_def/2),
357     "]",
358     nl_indent(Ctxt),
359     format_funcs(Ds, Ctxt),
360     nl_indent(Ctxt)
361     | "end"
362    ].
363
364format_funcs(Fs, Ctxt) ->
365    format_vseq(Fs,
366		"", "",
367		Ctxt,
368		fun format_def/2).
369
370format_def({N,V}, Ctxt0) ->
371    Ctxt1 = add_indent(Ctxt0, Ctxt0#ctxt.body_indent),
372    [format(N, Ctxt0),
373     " =",
374     nl_indent(Ctxt1)
375     | format(V, Ctxt1)
376    ].
377
378
379format_values(Vs, Ctxt) ->
380    [$<,
381     format_hseq(Vs, ",", add_indent(Ctxt, 1), fun format/2),
382     $>].
383
384format_bitstr(Node, Ctxt) ->
385    maybe_anno(Node, fun do_format_bitstr/2, Ctxt).
386
387do_format_bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Ctxt0) ->
388    Vs = [S, U, T, Fs],
389    Ctxt1 = add_indent(Ctxt0, 2),
390    Val = format(V, Ctxt1),
391    Ctxt2 = add_indent(Ctxt1, width(Val, Ctxt1) + 2),
392    ["#<", Val, ">(", format_hseq(Vs,",", Ctxt2, fun format/2), $)].
393
394format_clauses(Cs, Ctxt) ->
395    format_vseq(Cs, "", "", Ctxt, fun format_clause/2).
396
397format_clause(Node, Ctxt) ->
398    maybe_anno(Node, fun format_clause_1/2, Ctxt).
399
400format_clause_1(#c_clause{pats=Ps,guard=G,body=B}, Ctxt) ->
401    Ptxt = format_values(Ps, Ctxt),
402    Ctxt2 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
403    [Ptxt,
404     case is_trivial_guard(G) of
405	 true ->
406	     [" when ",
407	      format_guard(G, add_indent(Ctxt, width(Ptxt, Ctxt) + 6))];
408	 false ->
409	     [nl_indent(Ctxt2), "when ",
410	      format_guard(G, add_indent(Ctxt2, 2))]
411     end++
412     " ->",
413     nl_indent(Ctxt2) | format(B, Ctxt2)
414    ].
415
416is_trivial_guard(#c_literal{val=Val}) when is_atom(Val) -> true;
417is_trivial_guard(_) -> false.
418
419format_guard(Node, Ctxt) ->
420    maybe_anno(Node, fun format_guard_1/2, Ctxt).
421
422format_guard_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
423    Ctxt1 = add_indent(Ctxt0, 5),		%"call "
424    Mod = format(M, Ctxt1),
425    Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
426    Name = format(N, Ctxt2),
427    Ctxt3 = add_indent(Ctxt0, 4),
428    ["call ",Mod,":",Name,
429     nl_indent(Ctxt3),
430     $(,format_vseq(As, "",",", add_indent(Ctxt3, 1), fun format_guard/2),$)
431    ];
432format_guard_1(E, Ctxt) -> format_1(E, Ctxt).	%Anno already done
433
434%% format_hseq([Thing], Separator, Context, Fun) -> Txt.
435%%  Format a sequence horizontally on the same line with Separator between.
436
437format_hseq([H], _, Ctxt, Fun) ->
438    Fun(H, Ctxt);
439format_hseq([H|T], Sep, Ctxt, Fun) ->
440    Txt = [Fun(H, Ctxt)|Sep],
441    Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
442    [Txt|format_hseq(T, Sep, Ctxt1, Fun)];
443format_hseq([], _, _, _) -> "".
444
445%% format_vseq([Thing], LinePrefix, LineSuffix, Context, Fun) -> Txt.
446%%  Format a sequence vertically in indented lines adding LinePrefix
447%%  to the beginning of each line and LineSuffix to the end of each
448%%  line.  No prefix on the first line or suffix on the last line.
449
450format_vseq([H], _Pre, _Suf, Ctxt, Fun) ->
451    Fun(H, Ctxt);
452format_vseq([H|T], Pre, Suf, Ctxt, Fun) ->
453    [Fun(H, Ctxt),Suf,nl_indent(Ctxt),Pre|
454     format_vseq(T, Pre, Suf, Ctxt, Fun)];
455format_vseq([], _, _, _, _) -> "".
456
457format_list_tail(#c_literal{anno=[],val=[]}, _) -> "]";
458format_list_tail(#c_cons{anno=[],hd=H,tl=T}, Ctxt) ->
459    Txt = [$,|format(H, Ctxt)],
460    Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
461    [Txt|format_list_tail(T, Ctxt1)];
462format_list_tail(Tail, Ctxt) ->
463    ["|",format(Tail, add_indent(Ctxt, 1)),"]"].
464
465format_map_pair(Op, K, V, Ctxt0) ->
466    Ctxt1 = add_indent(Ctxt0, 1),
467    Txt = format(K, Ctxt1),
468    Ctxt2 = add_indent(Ctxt0, width(Txt, Ctxt1)),
469    [Txt,Op,format(V, Ctxt2)].
470
471indent(#ctxt{indent=N}) ->
472    if
473	N =< 0 ->
474	    "";
475	true ->
476           lists:duplicate(N div ?TAB_WIDTH, $\t) ++ spaces(N rem ?TAB_WIDTH)
477    end.
478
479nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
480
481spaces(0) -> "";
482spaces(1) -> " ";
483spaces(2) -> "  ";
484spaces(3) -> "   ";
485spaces(4) -> "    ";
486spaces(5) -> "     ";
487spaces(6) -> "      ";
488spaces(7) -> "       ".
489
490%% Undo indentation done by nl_indent/1.
491unindent(T, Ctxt) ->
492    unindent(T, Ctxt#ctxt.indent, []).
493
494unindent(T, N, C) when N =< 0 ->
495    [T|C];
496unindent([$\s|T], N, C) ->
497    unindent(T, N - 1, C);
498unindent([$\t|T], N, C) ->
499    Tab = ?TAB_WIDTH,
500    if N >= Tab ->
501	    unindent(T, N - Tab, C);
502       true ->
503	    unindent([spaces(Tab - N)|T], 0, C)
504    end;
505unindent([L|T], N, C) when is_list(L) ->
506    unindent(L, N, [T|C]).
507
508
509width(Txt, Ctxt) ->
510    width(Txt, 0, Ctxt, []).
511
512width([$\t|T], A, Ctxt, C) ->
513    width(T, A + ?TAB_WIDTH, Ctxt, C);
514width([$\n|T], _, Ctxt, C) ->
515    width(unindent([T|C], Ctxt), Ctxt);
516width([H|T], A, Ctxt, C) when is_list(H) ->
517    width(H, A, Ctxt, [T|C]);
518width([_|T], A, Ctxt, C) ->
519    width(T, A + 1, Ctxt, C);
520width([], A, Ctxt, [H|T]) ->
521    width(H, A, Ctxt, T);
522width([], A, _, []) -> A.
523
524add_indent(Ctxt, Dx) ->
525    Ctxt#ctxt{indent = Ctxt#ctxt.indent + Dx}.
526
527core_atom(A) -> io_lib:write_string(atom_to_list(A), $').
528
529
530is_simple_term(#c_tuple{es=Es}) ->
531    length(Es) < 4 andalso lists:all(fun is_simple_term/1, Es);
532is_simple_term(#c_var{}) -> true;
533is_simple_term(#c_literal{val=[_|_]}) -> false;
534is_simple_term(#c_literal{val=V}) -> not is_tuple(V);
535is_simple_term(_) -> false.
536
537segs_from_bitstring(<<H,T/bitstring>>) ->
538    [#c_bitstr{val=#c_literal{val=H},
539	       size=#c_literal{val=8},
540	       unit=#c_literal{val=1},
541	       type=#c_literal{val=integer},
542	       flags=#c_literal{val=[unsigned,big]}}|segs_from_bitstring(T)];
543segs_from_bitstring(<<>>) ->
544    [];
545segs_from_bitstring(Bitstring) ->
546    N = bit_size(Bitstring),
547    <<I:N>> = Bitstring,
548    [#c_bitstr{val=#c_literal{val=I},
549	      size=#c_literal{val=N},
550	      unit=#c_literal{val=1},
551	      type=#c_literal{val=integer},
552	      flags=#c_literal{val=[unsigned,big]}}].
553
554clean_anno_carefully(Node) ->
555    Anno = clean_anno_carefully_1(cerl:get_ann(Node)),
556    cerl:set_ann(Node, Anno).
557
558clean_anno_carefully_1([letrec_goto=Keep|Annos]) ->
559    [Keep|clean_anno_carefully_1(Annos)];
560clean_anno_carefully_1([_|Annos]) ->
561    clean_anno_carefully_1(Annos);
562clean_anno_carefully_1([]) -> [].
563