[m-rev.] For revew: a new, improved pretty printer

Ralph Becket rafe at csse.unimelb.edu.au
Wed Aug 1 18:05:26 AEST 2007


Zoltan Somogyi, Wednesday,  1 August 2007:
> On 01-Aug-2007, Ralph Becket <rafe at csse.unimelb.edu.au> wrote:
> > +:- type doc
> > +    --->    s(string)                   % Output a literal string.  Strings
> > +                                        %   containing newlines, hard
> > +                                        %   tabs, etc. will lead to strange
> > +                                        %   output.
> > +    ;       nl                          % Output a newline if the enclosing
> > +                                        %   group does not fit on the current
> > +                                        %   line.
> 
> I think the documentation would be much easier to read (and to write)
> in this style:
> 
>        ;        nl
>        		% Output a newline if the enclosing group does not fit
> 		% on the current line.

Hmm, in this case I prefer the style I've used.  Anybody want to cast a
tie-breaking vote?

> I would consider renaming the constructor s/1 to something else, both to make
> it more readable and to avoid the ambiguity with the constructor used in
> string.format.

What do you suggest?  Is this overloading of s/1 likely to cause
trouble?

> > +    ;       open_group                  % Open a new group (groups control
> > +                                        %   how nls are handled).
> > +    ;       close_group                 % Close a group.
> 
> Document how unmatched open_groups and close_groups are handled.

I'll add a comment to the effect that unmatched grouping and indentation
leads to undefined behaviour.

> 
> > +    ;       indent(string)              % Append a string to indentation.
> > +    ;       outdent                     % Remove the last indentation string.
> 
> Likewise
> 
> > +    ;       pp_list(list(univ), doc)    % Pretty print a list of items
> > +                                        %  using the given doc as a
> > +                                        %  separator between items.  Each
> > +                                        %  item - separator pair is placed
> > +                                        %  inside a group, preceded by nl
> > +                                        %  and set_arg_priority.
> 
> What is set_arg_priority? You have set_OP_priority below.

set_arg_priority is a function defined a few lines further on:

	    % set_arg_priority =
	    %   set_op_priority(ops.arg_priority(ops.init_mercury_op_table))
	    %
	    % This is a useful shorthand when pretty-printing term arguments.
	    %
	:- func set_arg_priority = doc.

> Also, items and separators are not pairs, since N items have N-1 separators.

How about this:

% pp_list([X1, X2, ..., Xn], Sep) expands into
%
%   docs([set_arg_priority, open_group, nl, pp_univ(X1), Sep, close_group,
%         set_arg_priority, open_group, nl, pp_univ(X2), Sep, close_group,
%         ...,
%         set_arg_priority, open_group, nl, pp_univ(Xn), close_group])
%
% although later list items will appear as just "..." if the term depth
% limit is reached.

> Are there limits on what docs are permissible or sensible separators?

No.

> > +    ;       pp_term(string, list(univ)) % Pretty print a term with zero or
> > +                                        %  more arguments.  If the term
> > +                                        %  corresponds to a Mercury operator
> > +                                        %  it will be printed with appropriate
> > +                                        %  fixity and, if necessary, in
> > +                                        %  parentheses.  The term name will be
> > +                                        %  quoted and escaped if necessary.
> 
> > +    ;       set_op_priority(ops.priority)
> > +                                        % Set the current priority for printing
> > +                                        %  operator terms with the correct
> > +                                        %  parenthesisation.
> 
> What is the scope of this effect? Why isn't the scope a doc supplied as an
> argument?

The scope extends to the next set_op_priority doc.

> 
> > +    ;       set_limit(pp_limit).        % Set the truncation limit.  This
> > +                                        %  should not be necessary for user
> > +                                        %  defined pretty printers!
> 
> I don't know which of several possible meanings of "truncation limit" you
> mean here (e.g. is the limit hard or soft?). However, regardless of the
> meaning, which is this part of a doc instead of an argument to the predicate
> that prints docs or converts them to strings? If it has to be a part of
> the doc for some reason, what is the scope of its effect?

By "truncation limit" I mean "term formatting depth limit".  It needs to
be part of the doc type because the algorithm works by first flattening
part of a group into a sequence of simpler docs then deciding how to
output those simpler docs.  The term formatting depth limit is reduced
every time a pp_univ, pp_list, or pp_term doc is expanded.  In the case
of the triangular limit, the depth limit after a pp_univ (say) is one
less than what it was before, not whatever the depth limit is after
processing the contents of the pp_univ.  Hence the flattened versions of
pp_univs etc. have to have some way of setting the correct depth limit
at the end.

I can add a comment explaining this, but I think the comment should go
in the implementation section.

-- Ralph
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list