[m-rev.] for review: start integrating stream typeclasses into stdlib

Julien Fischer juliensf at csse.unimelb.edu.au
Thu Oct 26 16:12:13 AEST 2006


For review by anyone.

Estimated hours taken: 2
Branches: main

Start integrating the new stream typeclasses into the rest of the
standard library.

library/io.m:
 	Make the standard text and binary files streams from the io
 	modules instances of the new stream typeclasses.
 	(Note: I've only made instances of the obvious types, we
 	 will probably want to define a few more, e.g.
 	 	:- type line ---> line(string)
 	).

 	Unrelated change: move the implementation of the function
 	version of io.error_message next to its predicate version.

library/pprint.m:
 	Generalise pprint.write so that it can write docs to any
 	arbitrary string writer.  (This is backwards compatible with
 	existing uses of this prediate.)

tests/hard_coded/Mmakefile:
tests/hard_coded/stream_tests.{m,exp,data}:
 	A short test of the new stream typeclasses.

Julien.

Index: library/io.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.361
diff -u -r1.361 io.m
--- library/io.m	24 Oct 2006 02:59:46 -0000	1.361
+++ library/io.m	26 Oct 2006 05:28:29 -0000
@@ -34,6 +34,7 @@
  :- import_module list.
  :- import_module map.
  :- import_module maybe.
+:- import_module stream.
  :- import_module string.
  :- import_module time.
  :- import_module univ.
@@ -1356,6 +1357,41 @@
  :- pred io.error_message(io.error::in, string::out) is det.

  %-----------------------------------------------------------------------------%
+%
+% Instances of the stream typeclass
+%
+
+:- instance stream.error(io.error).
+
+:- instance stream.stream(io.output_stream, io.state).
+:- instance stream.output(io.output_stream, io.state).
+:- instance stream.writer(io.output_stream, char,   io.state).
+:- instance stream.writer(io.output_stream, float,  io.state).
+:- instance stream.writer(io.output_stream, int,    io.state).
+:- instance stream.writer(io.output_stream, string, io.state).
+:- instance stream.writer(io.output_stream, univ,   io.state).
+:- instance stream.line_oriented(io.output_stream, io.state).
+
+:- instance stream.stream(io.input_stream, io.state).
+:- instance stream.input(io.input_stream, io.state, io.error).
+:- instance stream.reader(io.input_stream, char, io.state, io.error).
+
+:- instance stream.line_oriented(io.input_stream, io.state).
+:- instance stream.putback(io.input_stream, char, io.state, io.error).
+
+:- instance stream.stream(io.binary_output_stream, io.state).
+:- instance stream.output(io.binary_output_stream, io.state).
+:- instance stream.writer(io.binary_output_stream, int, io.state).
+:- instance stream.writer(io.binary_output_stream, string, io.state).
+:- instance stream.seekable(io.binary_output_stream, io.state).
+
+:- instance stream.stream(io.binary_input_stream,  io.state).
+:- instance stream.input(io.binary_input_stream,  io.state, io.error).
+:- instance stream.reader(io.binary_input_stream, int, io.state, io.error).
+:- instance stream.putback(io.binary_input_stream, int, io.state, io.error).
+:- instance stream.seekable(io.binary_input_stream, io.state).
+
+%-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%

  :- implementation.
@@ -5097,6 +5133,9 @@

  io.make_io_error(Error) = io_error(Error).

+io.error_message(Error) = Msg :-
+    io.error_message(Error, Msg).
+
  io.error_message(io_error(Error), Error).

  %-----------------------------------------------------------------------------%
@@ -8964,12 +9003,189 @@
      }
  ").

-/*---------------------------------------------------------------------------*/
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+%
+% Instances of the stream typeclass
+%
+
+:- instance stream.error(io.error) where [
+    func(stream.error_message/1) is io.error_message
+].

  %-----------------------------------------------------------------------------%
+%
+% Text input streams
+%
+
+:- instance stream.stream(io.input_stream, io.state) where [
+    pred(name/4) is io.input_stream_name
+].
+
+:- instance stream.input(io.input_stream, io.state, io.error) where [].
+
+:- instance stream.reader(io.input_stream, char, io.state, io.error)
+    where
+[
+    ( get(Stream, Result, !IO) :-
+        io.read_char(Stream, Result0, !IO),
+        Result = io.result_to_stream_result(Result0)
+    )
+].
+
+:- instance stream.reader(io.input_stream, string, io.state, io.error) 
+    where
+[
+    ( get(Stream, Result, !IO) :-
+        io.read_line_as_string(Stream, Result0, !IO),
+        Result = io.result_to_stream_result(Result0)
+    )
+].
+ 
+:- instance stream.putback(io.input_stream, char, io.state, io.error) where
+[
+    pred(unget/4) is io.putback_char
+].
+
+:- func io.result_to_stream_result(io.result(T)) = stream.result(T, io.error).
+
+io.result_to_stream_result(ok(T)) = ok(T).
+io.result_to_stream_result(eof) = eof.
+io.result_to_stream_result(error(Error)) = error(Error).
+
+
+:- instance stream.line_oriented(io.input_stream, io.state) where
+[
+    pred(get_line/4) is io.get_line_number,
+    pred(set_line/4) is io.set_line_number
+].
+
  %-----------------------------------------------------------------------------%
-% Ralph Becket <rwab1 at cl.cam.ac.uk> 27/04/99
-%   Functional forms added.
+%
+% Text output streams
+%

-io.error_message(Error) = Msg :-
-    io.error_message(Error, Msg).
+:- instance stream.stream(io.output_stream, io.state) where [
+    pred(name/4) is io.output_stream_name
+].
+
+:- instance stream.output(io.output_stream, io.state) where [
+    pred(flush/3) is io.flush_output
+].
+
+:- instance stream.writer(io.output_stream, char, io.state)
+    where
+[
+    pred(put/4) is io.write_char
+].
+
+:- instance stream.writer(io.output_stream, float, io.state)
+    where
+[
+    pred(put/4) is io.write_float
+].
+
+:- instance stream.writer(io.output_stream, int, io.state)
+    where
+[
+    pred(put/4) is io.write_int
+].
+
+:- instance stream.writer(io.output_stream, string, io.state)
+    where
+[
+    pred(put/4) is io.write_string
+].
+
+:- instance stream.writer(io.output_stream, univ, io.state)
+    where
+[
+    pred(put/4) is io.write_univ
+].
+
+:- instance stream.line_oriented(io.output_stream, io.state) where
+[
+    pred(get_line/4) is io.get_output_line_number,
+    pred(set_line/4) is io.set_output_line_number
+].
+
+%-----------------------------------------------------------------------------%
+%
+% Binary input streams
+%
+
+:- instance stream.stream(io.binary_input_stream, io.state)
+    where
+[
+    pred(name/4) is io.binary_input_stream_name
+].
+
+:- instance stream.input(io.binary_input_stream, io.state, io.error)
+    where [].
+
+:- instance stream.reader(io.binary_input_stream, int, io.state, io.error)
+    where
+[
+    ( get(Stream, Result, !IO) :-
+        io.read_byte(Stream, Result0, !IO),
+        Result = io.result_to_stream_result(Result0)
+    )
+]. 
+
+:- instance stream.putback(io.binary_input_stream, int, io.state, io.error)
+    where
+[
+    pred(unget/4) is io.putback_byte
+].
+
+:- instance stream.seekable(io.binary_input_stream, io.state)
+    where
+[
+    ( seek(Stream, Whence0, OffSet, !IO) :-
+        Whence = stream_whence_to_io_whence(Whence0),
+        io.seek_binary_input(Stream, Whence, OffSet, !IO)
+    )
+]. 
+
+:- func stream_whence_to_io_whence(stream.whence) = io.whence.
+
+stream_whence_to_io_whence(set) = set.
+stream_whence_to_io_whence(cur) = cur.
+stream_whence_to_io_whence(end) = end.
+
+%-----------------------------------------------------------------------------%
+%
+% Binary output streams
+%
+
+:- instance stream.stream(io.binary_output_stream, io.state) where [
+    pred(name/4) is io.binary_output_stream_name
+].
+
+:- instance stream.output(io.binary_output_stream, io.state) where [
+    pred(flush/3) is io.flush_binary_output
+].
+
+:- instance stream.writer(io.binary_output_stream, int, io.state)
+    where
+[
+    pred(put/4) is io.write_byte
+].
+
+:- instance stream.writer(io.binary_output_stream, string, io.state)
+    where
+[
+    pred(put/4) is io.write_bytes
+].
+
+:- instance stream.seekable(io.binary_output_stream, io.state)
+    where
+[
+    ( seek(Stream, Whence0, OffSet, !IO) :-
+        Whence = stream_whence_to_io_whence(Whence0),
+        io.seek_binary_output(Stream, Whence, OffSet, !IO)
+    )
+]. 
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
Index: library/pprint.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.26
diff -u -r1.26 pprint.m
--- library/pprint.m	27 Sep 2006 06:16:41 -0000	1.26
+++ library/pprint.m	26 Oct 2006 05:43:47 -0000
@@ -156,6 +156,7 @@
  :- import_module char.
  :- import_module io.
  :- import_module list.
+:- import_module stream.
  :- import_module string.
  :- import_module univ.

@@ -366,8 +367,11 @@
      %
  :- pred write(int::in, T::in, io::di, io::uo) is det <= doc(T).

-:- pred write(io.output_stream::in, int::in, T::in, io::di, io::uo) is det
-    <= doc(T).
+    % Write docs to the specified string writer stream in pretty printed
+    % format.  The int argument specifies a page width in characters.
+    %
+:- pred write(Stream::in, int::in, T::in, State::di, State::uo) is det
+    <= ( doc(T), stream.writer(Stream, string, State) ).

  %-----------------------------------------------------------------------------%
  %-----------------------------------------------------------------------------%
@@ -453,8 +457,8 @@
  write(W, X, !IO) :-
      layout_best(io.write_string, W, doc(X), !IO).

-write(Stream, W, X, !IO) :-
-    layout_best(io.write_string(Stream), W, doc(X), !IO).
+write(Stream, W, X, !State) :-
+    layout_best(put(Stream), W, doc(X), !State).

  %-----------------------------------------------------------------------------%

Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.298
diff -u -r1.298 Mmakefile
--- tests/hard_coded/Mmakefile	9 Oct 2006 06:40:26 -0000	1.298
+++ tests/hard_coded/Mmakefile	26 Oct 2006 06:01:30 -0000
@@ -185,6 +185,7 @@
  	solver_ite_inits \
  	space \
  	stable_sort \
+	stream_test \
  	string_alignment \
  	string_alignment_bug \
  	string_loop \
@@ -573,6 +574,9 @@
  nonascii_gen:	nonascii_gen.c
  	$(CC) nonascii_gen.c -o nonascii_gen

+stream_test.out: stream_test
+	./stream_test < stream_test.data > stream_test.out
+
  # The trace_goal_env_1 and trace_goal_env_2 test cases differ from each other
  # only in that the latter is executed with the TRACE_ABC environment variable
  # set.
Index: tests/hard_coded/stream_test.data
===================================================================
RCS file: tests/hard_coded/stream_test.data
diff -N tests/hard_coded/stream_test.data
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/stream_test.data	26 Oct 2006 05:58:51 -0000
@@ -0,0 +1,3 @@
+abcdefghijklmnopqrstuvwxyz
+0123456789
+~!@#$%^&*()_+
Index: tests/hard_coded/stream_test.exp
===================================================================
RCS file: tests/hard_coded/stream_test.exp
diff -N tests/hard_coded/stream_test.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/stream_test.exp	26 Oct 2006 05:58:51 -0000
@@ -0,0 +1,16 @@
+561
+Hello World!
+a
+[foo, bar, baz]
+[
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo, 
+ foo]
+['\n', '+', '_', ')', '(', '*', '&', '^', '%', '$', '#', '@', '!', '~', '\n', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '\n', 'z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
Index: tests/hard_coded/stream_test.m
===================================================================
RCS file: tests/hard_coded/stream_test.m
diff -N tests/hard_coded/stream_test.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/stream_test.m	26 Oct 2006 05:58:51 -0000
@@ -0,0 +1,42 @@
+:- module stream_test.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module char.
+:- import_module list.
+:- import_module pprint.
+:- import_module stream.
+:- import_module univ.
+
+:- type foo ---> foo ; bar ; baz.
+
+main(!IO) :-
+	io.stdout_stream(Stdout, !IO),
+	put(Stdout, 561, !IO),
+	put(Stdout, "\nHello World!\n", !IO),
+	put(Stdout, 'a', !IO),
+	put(Stdout, "\n", !IO),
+	put(Stdout, univ([foo, bar, baz]), !IO),
+	put(Stdout, "\n", !IO),
+	list.duplicate(10, foo, ListFoo),
+	pprint.write(Stdout, 4, to_doc(ListFoo), !IO),
+	io.nl(Stdout, !IO),
+	io.stdin_stream(Stdin, !IO),
+	input_stream_fold(Stdin, char_list_cons, [], PartialResult, !IO),
+	(
+		PartialResult = ok(Result),
+		io.write(Result, !IO),
+		io.nl(!IO)
+	;
+		PartialResult = error(_, _),
+		io.write_string("TEST FAILED\n", !IO)
+	).
+
+:- pred char_list_cons(char::in, list(char)::in, list(char)::out) is det.
+
+char_list_cons(X, Xs, [ X | Xs ]).

--------------------------------------------------------------------------
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