library/string.builder.m:
Add a predicate that tests whether the total length of the string
implicit in a string builder is within a limit, or not.
Add a function that returns that total length.
NEWS.md:
Announce the new predicate and function.
compiler/parse_tree_out_term.m:
Use the new predicate to optimize a test.
compiler/parse_tree_out_info.m:
... by making string builders instances of the "output" typeclass,
whose operations are the base level of the code of parse_tree_out*.m.
Strings were already instances of "output", but the use of this instance
was problematic for large structures such as entire files. This is because
if the final string was constructed by adding together N atomic strings,
then the construction of the final string involves copying each of those
atomic strings about N/2 times on average.
With the string builder instance, each string is copied just twice:
when it is added to the string builder state, and when that state is
converted to the final string.
library/string.builder.m:
Add three new predicates, append_char, append_string and append_strings.
The first two are copied from existing instance methods; making them
separate predicates allows them to be invoked using a first order call,
instead of a method call. The third is just for convenience. All three
are used by the new code in parse_tree_out_info.m.
NEWS.md:
Announce the new predicates in string.builder.m.
library/term_io.m:
library/stream.string_writer.m:
Many predicates in these two modules have long had two typeclass
constraints:
stream.writer(Stream, string, State)
stream.writer(Stream, char, State)
This diff eliminates the second constraint, for two reasons.
The first is ergonomics; writing one constraint is faster than writing two,
and likewise for reading. The second is efficiency: we have to pass around
just one typeclass info, not two.
There is a tradeoff, which is that to output characters, we now
have to call char_to_string. For the string.builder instance of
stream.writer, this has no efficiency downside, because the char instance
of stream.string_writer itself calls char_to_string. For the I/O state
instance of stream.string_writer, there is a downside because io.write_char
does not need to convert the character to a string, but the downside
is negligible compared to the overall cost of I/O. And in any case,
most of the places where the code of either of these modules wrote out
characters, it wrote out character *constants*, which this diff converts
to string constants, eliminating the runtime conversion and its cost.
library/string.builder.m:
Use string.char_to_string, instead of its older synonym string.from_char,
in the char instance of stream.string_writer.
library/term_io.m:
Move the base operations of term_io.m to the structure we use
in parse_tree_out*.m in the compiler, where for every type X,
there is a function X_to_string, and two predicates write_X and format_X,
with the former operating on I/O states, and the latter operating on
arbitrary streams. The idea is to apply the "don't repeat yourself"
principle by having both X_to_string and write_X just call format_X.
Apply that principle here as well, with one minor exception,
which is that for some values of X, both write_X and format_X are
implemented in terms of X_to_string.
Impose the X_to_string, write_X, format_X naming scheme. The ancient code
already in term_io.m had (each for some values of X) had
- some of these functions/predicates missing
- inconsistent names, in that write_X/N did I/O while write_X/(N+1)
wrote to arbitrary streams
- names that were inconsistent in another way, in that write_X/N did
I/O of values of type X, but the function to convert X to string
was NOT named X_to_string.
Keep some of the misnamed functions around permanently, because
some of the names for fitting into the new scheme, such as
"escaped_string_to_string", would be strange.
Keep the rest of the misnamed functions and all the misnamed predicates
around temporarily, with commented-out obsolete pragmas. I expect
to make these pragmas active when the rest of term_io.m is converted
to this scheme.
To prepare for that, use string.builder, not string, as the
stream.writer instance to implement X_to_string, because of its
better algorithmic complexity, which is needed mainly for terms
of nontrivial size.
Consistently put operations on each X in the order X_to_string,
write_X and format_X.
NEWS.md:
List all the new predicates and functions.
configure.ac:
Require the installed compiler to contain the fix which allows
a typespec pragma for an obsolete predicate or function.
browser/interactive_query.m:
compiler/hlds_out_util.m:
compiler/parse_tree_out_clause.m:
compiler/parse_tree_out_cons_id.m:
compiler/parse_tree_out_info.m:
compiler/parse_tree_out_pragma.m:
compiler/parse_tree_out_sym_name.m:
compiler/parse_tree_out_type_repn.m:
library/pretty_printer.m:
library/stream.string_writer.m:
library/string.builder.m:
mdbcomp/trace_counts.m:
Update all references to the newly-obsolete predicates and functions.
library/string.to_string.m:
Improve variable names.
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.
COPYING.LIB:
Add a special linking exception to the LGPL.
*:
Update references to COPYING.LIB.
Clean up some minor errors that have accumulated in copyright
messages.
Estimated hours taken: 0.5
Branches: main.
Move the string builder stream from extras to the standard library.
library/string.builder.m:
Move stream_util.string_builder to string.builder.
Use builtin.copy instead of unsafe_promise_unique in the implementation
of put/4 for the string builder stream.
library/string.m:
Include string.builder.
tests/hard_coded/Mmakefile:
tests/hard_coded/string_builder_test.exp:
tests/hard_coded/string_builder_test.m:
Add a test case.
extras/Mmakefile:
extras/README:
extras/stream/Mmakefile:
extras/stream/README:
extras/stream/impure.m:
extras/stream/lowlevel.m:
extras/stream/stream_old.m:
extras/stream/stream_util.m:
extras/stream/stream_util.string_builder.m:
extras/stream/tests/Makefile:
extras/stream/tests/stream_util_test.exp:
extras/stream/tests/stream_util_test.m:
Completely remove the streams modules from extras. These modules
are all deprecated now.