[m-rev.] for post-commit review: improve pretty_printer speed by a lot

Peter Wang novalazy at gmail.com
Wed Aug 31 10:51:21 AEST 2022


On Tue, 30 Aug 2022 13:35:36 +1000 "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
> +output_indent_stack(Stream, IndentStack, !IO) :-
> +    (
> +        IndentStack = indent_empty
> +    ;
> +        IndentStack = indent_user(PrevStack, IndentStr, _NumCPs),
> +        output_indent_stack(Stream, PrevStack, !IO),
> +        stream.put(Stream, IndentStr, !IO)
> +    ;
> +        IndentStack = indent_std(PrevStack, IndentLevels, _NumCPs),
> +        output_indent_stack(Stream, PrevStack, !IO),
> +        output_std_indent_levels(Stream, IndentLevels, !IO)
> +    ).
> +
> +:- pred output_std_indent_levels(Stream::in, int::in,
> +    State::di, State::uo) is det <= stream.writer(Stream, string, State).
> +:- pragma type_spec(pred(output_std_indent_levels/4),
> +    (Stream = io.output_stream, State = io.state)).
> +
> +output_std_indent_levels(Stream, NumLevels, !IO) :-
> +    % We try to amortize the overhead of stream.put over as large a part
> +    % of the overall indentation as we can.
> +    ( if NumLevels >= 30 then

Both work, but I think NumLevels > 30 is clearer.

> +        ( if std_indent(30, IndentStr) then
> +            stream.put(Stream, IndentStr, !IO),
> +            output_std_indent_levels(Stream, NumLevels - 30, !IO)
> +        else
> +            unexpected($pred, "std_indent failed 30+")
> +        )
> +    else if NumLevels > 0 then
> +        ( if std_indent(NumLevels, IndentStr) then
> +            stream.put(Stream, IndentStr, !IO)
> +        else
> +            unexpected($pred, "std_indent failed <30")
> +        )
> +    else
> +        true
> +    ).

> @@ -1055,6 +1130,104 @@ decrement_func_limit(triangular(N), triangular(N - 1)).
>  %---------------------------------------------------------------------------%
>  %---------------------------------------------------------------------------%
>  
> +:- type indent_stack
> +    --->    indent_empty
> +            % No indent at all. Number of code points is zero.
> +    ;       indent_user(
> +                % The indentation after which this indentation is added.
> +                user_prevstack          :: indent_stack,
> +
> +                % Indentation added by a non-standard indent() function.
> +                user_indent_string      :: string,
> +
> +                % The total number of code points in user_prevstack and
> +                % user_extra_indent. Must be the sum of

user_indent_string

> +                % count_indent_codepoints(user_prevstack) and
> +                % string.count_codepoints(user_indent_string).
> +                user_total_code_points  :: int
> +            )
> +    ;       indent_std(
> +                % The indentation after which this indentation is added.
> +                std_prevstack           :: indent_stack,
> +
> +                % The number of extra standard indent levels added
> +                % after std_prevstack. Each indent level consists of two
> +                % spaces.
> +                std_extra_indent_levels :: int,
> +
> +                % The total number of code points in user_prevstack and
> +                % user_extra_indent. Must be the sum of
> +                % count_indent_codepoints(user_prevstack) and
> +                % 2 * std_extra_indent_levels.

std_prevstack and std_extra_indent_levels

> +                std_total_code_points   :: int
> +            ).

Peter


More information about the reviews mailing list