[m-rev.] for review: move string builder stream to standard library

Ian MacLarty maclarty at csse.unimelb.edu.au
Fri Apr 20 11:10:37 AEST 2007


On Thu, Apr 19, 2007 at 05:50:22PM +1000, Julien Fischer wrote:
> 
> On Thu, 19 Apr 2007, Ian MacLarty wrote:
> 
> >For review by anyone.
> >
> >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.
> 
> You also need to update the predicate mercury_std_library_module/1
> in library/library.m.
> 

Done.

> >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.
> 
> (For the record, Ian and I discussed this and decided that it was simpler
> to just delete the stream package from extras, rather than expend the
> any effort maintaining it; the stream support in the stdlib offers
> significantly more functionality than this ever did.)
> 
> >Index: library/string.builder.m
> >===================================================================
> >RCS file: library/string.builder.m
> >diff -N library/string.builder.m
> >--- /dev/null	1 Jan 1970 00:00:00 -0000
> >+++ library/string.builder.m	19 Apr 2007 05:14:15 -0000
> >@@ -0,0 +1,92 @@
> >+%-----------------------------------------------------------------------------%
> >+% vim: ft=mercury ts=4 sw=4 et
> >+%-----------------------------------------------------------------------------%
> >+% Copyright (C) 2006 The University of Melbourne.
> >+% This file may only be copied under the terms of the GNU Library General
> >+% Public License - see the file COPYING.LIB in the Mercury distribution.
> >+%-----------------------------------------------------------------------------%
> >+%
> >+% File: string.builder.m.
> >+% Main author: maclarty.
> >+%
> >+% This module implements a string builder stream.  It can be used to
> >+% build up a string using string or character writers.
> >+%
> >+%-----------------------------------------------------------------------------%
> >+%-----------------------------------------------------------------------------%
> >+
> >+:- module string.builder.
> >+:- interface.
> >+
> >+:- import_module char.
> >+:- import_module stream.
> >+
> >+%-----------------------------------------------------------------------------%
> >+
> >+:- type string_builder_stream.
> 
> I suggest calling that string_builder_handle.  The "stream" is really
> the combination of both that and the state.
> 

I've renamed it to just string.builder.handle.

> >+:- type string_builder_state.
> >+
> >+:- pred init(string_builder_stream::out, string_builder_state::uo) is det.
> 
> It may be worth having a TODO list somewhere in the implementation
> section that mentions that if the restriction on repeated variables
> in typeclass instances is lifted then this should actually be:
> 
> 	:- type string_builder_stream(T).
> 	:- type string_builder_state(T).
> 
> 	:- some	[T] pred init(string_build_stream(T)::out,
> 		string_builder_state(T)::uo) is det.
> 

I think a better idea might be to just expose the implementation of the
handle type to make it clear that it's a constant.  This avoids the problem
of using the correct handle with the correct state altogether, because you
always use the same handle and it's only the state that varies.  Have a
look at the interdiff at the end of this email and see what you think.

> >+:- instance stream.stream(string_builder_stream, string_builder_state).
> >+
> >+:- instance stream.output(string_builder_stream, string_builder_state).
> >+
> >+:- instance stream.writer(string_builder_stream, string, 
> >string_builder_state).
> >+:- instance stream.writer(string_builder_stream, char, 
> >string_builder_state).
> >+
> >+:- func string_builder_state_to_string(string_builder_state::di) = 
> >(string::uo)
> >+    is det.
> 
> I would also provide to_string/1 as a synonym since that convention is
> followed throughout much of the library.
> 

I've added to_string and deleted string_builder_state_to_string.

Ian.

diff -u library/string.builder.m library/string.builder.m
--- library/string.builder.m	19 Apr 2007 05:14:15 -0000
+++ library/string.builder.m	20 Apr 2007 01:00:00 -0000
@@ -12,7 +12,19 @@
 % This module implements a string builder stream.  It can be used to
 % build up a string using string or character writers.
 %
-%-----------------------------------------------------------------------------%
+% To build up a string using this module, you first construct an initial
+% string builder state by calling the init function.  You can then use
+% any instances of stream.writer that write strings or characters to update the
+% string builder state, using string.builder.handle as the stream argument.
+% Once you've finished writing to the string builder you can get the final
+% string by calling string.builder.to_string/1.
+%
+% For example:
+%
+%     State0 = string.builder.init,
+%     stream.string_writer.put_int(string.builder.handle, 5, State0, State),
+%     Str = string.builder.to_string(State),  % Str = "5".
+%
 %-----------------------------------------------------------------------------%
 
 :- module string.builder.
@@ -23,21 +35,21 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type string_builder_stream.
+:- type handle
+    --->    handle.
 
-:- type string_builder_state.
+:- type state.
 
-:- pred init(string_builder_stream::out, string_builder_state::uo) is det.
+:- func init = (string.builder.state::uo) is det.
 
-:- instance stream.stream(string_builder_stream, string_builder_state).
+:- instance stream.stream(string.builder.handle, string.builder.state).
 
-:- instance stream.output(string_builder_stream, string_builder_state).
+:- instance stream.output(string.builder.handle, string.builder.state).
 
-:- instance stream.writer(string_builder_stream, string, string_builder_state).
-:- instance stream.writer(string_builder_stream, char, string_builder_state).
+:- instance stream.writer(string.builder.handle, string, string.builder.state).
+:- instance stream.writer(string.builder.handle, char, string.builder.state).
 
-:- func string_builder_state_to_string(string_builder_state::di) = (string::uo)
-    is det.
+:- func to_string(string.builder.state::di) = (string::uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -46,46 +58,43 @@
 
 :- import_module list.
 
-:- type string_builder_state
-    --->    string_builder_state(list(string)).
-
-:- type string_builder_stream
-    --->    string_builder_stream.
+:- type state
+    --->    state(list(string)).
 
-init(string_builder_stream, string_builder_state([])).
+init = state([]).
 
-:- instance stream.stream(string_builder_stream, string_builder_state)
+:- instance stream.stream(string.builder.handle, string.builder.state)
         where [
     name(_, "<<string builder stream>>", !State)
 ].
 
-:- instance stream.output(string_builder_stream, string_builder_state)
+:- instance stream.output(string.builder.handle, string.builder.state)
         where [
     flush(_, !State)
 ].
 
-:- instance stream.writer(string_builder_stream, string, string_builder_state)
+:- instance stream.writer(string.builder.handle, string, string.builder.state)
         where [
     ( put(_, String, !State) :-
-        !.State = string_builder_state(StringList0),
+        !.State = state(StringList0),
         copy(String, UniqueString),
         StringList = [UniqueString | StringList0],
-        !:State = string_builder_state(StringList)
+        !:State = state(StringList)
     )
 ].
 
-:- instance stream.writer(string_builder_stream, char, string_builder_state)
+:- instance stream.writer(string.builder.handle, char, string.builder.state)
         where [
     ( put(_, Char, !State) :-
-        !.State = string_builder_state(StringList0),
+        !.State = state(StringList0),
         StringList = [string.from_char(Char) | StringList0],
-        !:State = string_builder_state(StringList)
+        !:State = state(StringList)
     )
 ].
 
-string_builder_state_to_string(State) = String :-
-    State = string_builder_state(StringList),
-    String = string.join_list("", list.reverse(StringList)).
+to_string(State) = String :-
+    State = state(StringList),
+    String = string.append_list(list.reverse(StringList)).
 
 %-----------------------------------------------------------------------------%
 :- end_module string.builder.
diff -u tests/hard_coded/string_builder_test.m tests/hard_coded/string_builder_test.m
--- tests/hard_coded/string_builder_test.m	19 Apr 2007 04:17:19 -0000
+++ tests/hard_coded/string_builder_test.m	20 Apr 2007 01:02:01 -0000
@@ -15,12 +15,14 @@
 :- import_module pprint.
 :- import_module stream.
 :- import_module stream.string_writer.
+:- import_module string.
 :- import_module string.builder.
 :- import_module term_to_xml.
 
 main(!IO) :-
     some [!State] (
-        string.builder.init(Stream, !:State),
+        !:State = string.builder.init,
+        Stream = string.builder.handle,
         put(Stream, "Hello", !State),
         put(Stream, ',', !State),
         put(Stream, " world!", !State),
@@ -34,5 +36,5 @@
         string_writer.format(Stream, "%.2f", [f(3.14)], !State),
         put(Stream, "\n", !State),
-        String = string_builder_state_to_string(!.State),
+        String = string.builder.to_string(!.State),
         io.write_string(String, !IO)
     ).
only in patch2:
unchanged:
--- NEWS	12 Apr 2007 04:31:09 -0000	1.453
+++ NEWS	20 Apr 2007 00:37:11 -0000
@@ -137,6 +137,10 @@
 * We have added a function construct.get_functor_lex/2 which converts
   an ordinal functor number into a lexicographic functor number.
 
+* A new module string.builder has been added to the standard library.
+  The new module provides instances of the stream typeclasses that can
+  be used to build up a string using char and string writers.
+
 Changes to the Mercury compiler:
 
 * The compiler now issues a warning when an inst declaration is not
only in patch2:
unchanged:
--- library/library.m	16 Mar 2007 21:00:24 -0000	1.103
+++ library/library.m	20 Apr 2007 00:38:49 -0000
@@ -254,6 +254,7 @@
 mercury_std_library_module("stream").
 mercury_std_library_module("stream.string_writer").
 mercury_std_library_module("string").
+mercury_std_library_module("string.builder").
 mercury_std_library_module("svarray").
 mercury_std_library_module("svbag").
 mercury_std_library_module("svbimap").
--------------------------------------------------------------------------
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