[m-rev.] for review: add unboxed_readers to the stream module
Dirk Ziegemeyer
dirk at ziegemeyer.de
Sat Apr 18 16:48:44 AEST 2020
Hi Julien,
maybe change naming of the new instance to stream.reader_unboxed to be consistent with
io.read_char vs.
io.read_char_unboxed
Dirk
> Am 18.04.2020 um 07:34 schrieb Julien Fischer <jfischer at opturion.com>:
>
>
> For review by anyone.
>
> ------------------------
>
> Add unboxed_readers to the stream module.
>
> library/stream.m:
> Add a new type of reader, unboxed_reader. These provide a 'get'
> operation that does not need to box its output in the non-error case.
>
> library/io.m:
> Add an unboxed_reader instance for text_input_streams and chars.
>
> NEWS:
> Announce the addition.
>
> Julien.
>
> diff --git a/NEWS b/NEWS
> index 7032804..bf0d9ef 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -144,6 +144,12 @@ Changes to the Mercury standard library
> - func `keys_as_set/1`
> - pred `keys_as_set/2`
>
> +### Changes to the `stream` module
> +
> +* We have added a new `reader/4` subclass, `unboxed_reader/4`. This subclass
> + allows readers to provide a `get` operation that avoids boxing non-error
> + outputs.
> +
> ### Changes to the `thread.channel` module
>
> * The following predicate has been deprecated and will be removed in a future
> diff --git a/library/io.m b/library/io.m
> index f525daf..91c16ff 100644
> --- a/library/io.m
> +++ b/library/io.m
> @@ -1949,6 +1949,7 @@
> :- instance stream.stream(text_input_stream, io).
> :- instance stream.input(text_input_stream, io).
> :- instance stream.reader(text_input_stream, char, io, io.error).
> +:- instance stream.unboxed_reader(text_input_stream, char, io, io.error).
> :- instance stream.reader(text_input_stream, line, io, io.error).
> :- instance stream.reader(text_input_stream, text_file, io, io.error).
>
> @@ -2294,7 +2295,16 @@
> [
> ( get(Stream, Result, !IO) :-
> read_char(Stream, Result0, !IO),
> - Result = io.result_to_stream_result(Result0)
> + Result = io.result1_to_stream_result1(Result0)
> + )
> +].
> +
> +:- instance stream.unboxed_reader(input_stream, char, io, io.error)
> + where
> +[
> + ( unboxed_get(Stream, Result, Char, !IO) :-
> + read_char_unboxed(Stream, Result0, Char, !IO),
> + Result = io.result0_to_stream_result0(Result0)
> )
> ].
>
> @@ -2336,18 +2346,24 @@
> pred(unget/4) is putback_char
> ].
>
> -:- func result_to_stream_result(io.result(T)) = stream.result(T, io.error).
> -
> -result_to_stream_result(ok(T)) = ok(T).
> -result_to_stream_result(eof) = eof.
> -result_to_stream_result(error(Error)) = error(Error).
> -
> :- instance stream.line_oriented(input_stream, io) where
> [
> pred(get_line/4) is io.get_line_number,
> pred(set_line/4) is io.set_line_number
> ].
>
> +:- func result1_to_stream_result1(io.result(T)) = stream.result(T, io.error).
> +
> +result1_to_stream_result1(ok(T)) = ok(T).
> +result1_to_stream_result1(eof) = eof.
> +result1_to_stream_result1(error(Error)) = error(Error).
> +
> +:- func result0_to_stream_result0(io.result) = stream.result(io.error).
> +
> +result0_to_stream_result0(ok) = ok.
> +result0_to_stream_result0(eof) = eof.
> +result0_to_stream_result0(error(Error)) = error(Error).
> +
> %---------------------%
> %
> % Text output streams.
> @@ -2458,7 +2474,7 @@ result_to_stream_result(error(Error)) = error(Error).
> [
> ( get(Stream, Result, !IO) :-
> read_byte(Stream, Result0, !IO),
> - Result = result_to_stream_result(Result0)
> + Result = result1_to_stream_result1(Result0)
> )
> ].
>
> @@ -2467,7 +2483,7 @@ result_to_stream_result(error(Error)) = error(Error).
> [
> ( get(Stream, Result, !IO) :-
> read_binary_int8(Stream, Result0, !IO),
> - Result = result_to_stream_result(Result0)
> + Result = result1_to_stream_result1(Result0)
> )
> ].
>
> @@ -2476,7 +2492,7 @@ result_to_stream_result(error(Error)) = error(Error).
> [
> ( get(Stream, Result, !IO) :-
> read_binary_uint8(Stream, Result0, !IO),
> - Result = result_to_stream_result(Result0)
> + Result = result1_to_stream_result1(Result0)
> )
> ].
>
> diff --git a/library/stream.m b/library/stream.m
> index 60a599a..6581a2c 100644
> --- a/library/stream.m
> +++ b/library/stream.m
> @@ -110,10 +110,11 @@
> % The get operation should block until the next unit is available,
> % or the end of the stream or an error is detected.
> %
> - % If a call to get/4 returns `eof', all further calls to get/4 or
> - % bulk_get/9 for that stream return `eof'. If a call to get/4
> - % returns `error(...)', all further calls to get/4 or bulk_get/4 for
> - % that stream return an error, although not necessarily the same one.
> + % If a call to get/4 returns `eof', all further calls to get/4,
> + % unboxed_get/5 or bulk_get/9 for that stream return `eof'. If a call to
> + % get/4 returns `error(...)', all further calls to get/4, unboxed_get/5 or
> + % bulk_get/4 for that stream return an error, although not necessarily the
> + % same one.
> %
> % XXX We should provide an interface to allow the user to reset the
> % error status to try again if an error is transient.
> @@ -122,6 +123,30 @@
> State::di, State::uo) is det
> ].
>
> + % An unboxed_reader stream is like a reader stream except that it provides
> + % an interface that avoids a memory allocation when there is no error.
> + %
> +:- typeclass unboxed_reader(Stream, Unit, State, Error)
> + <= (input(Stream, State), error(Error), (Stream, Unit -> Error)) where
> +[
> + % Get the next unit from the given stream.
> + %
> + % The unboxed_get operation should block until the next unit is available,
> + % or the end of the stream or an error is detected.
> + %
> + % If a call to unboxed_get/5 returns `eof', all further calls to get/4,
> + % unboxed_get/5 or bulk_get/9 for that stream return `eof'. If a call to
> + % unboxed_get/5 returns `error(...)', all further calls to get/4,
> + % unboxed_get/5 or bulk_get/4 for that stream return an error, although not
> + % necessarily the same one.
> + %
> + % XXX We should provide an interface to allow the user to reset the
> + % error status to try again if an error is transient.
> + %
> + pred unboxed_get(Stream::in, result(Error)::out, Unit::out,
> + State::di, State::uo) is det
> +].
> +
> % A bulk_reader stream is a subclass of specific input stream that can
> % be used to read multiple items of data of a specific type from that
> % input stream into a specified container. For example, binary input
> @@ -152,10 +177,10 @@
> % starting at Index will not fit in !Store.
> %
> % If a call to bulk_get/4 returns less than NumItems items, all further
> - % calls to get/4 or bulk_get/4 for that stream return no items. If a call
> - % to bulk_get/9 returns `error(...)', all further calls to get/4 or
> - % bulk_get/9 for that stream return an error, although not necessarily
> - % the same one.
> + % calls to get/4, unboxed_get/5 or bulk_get/4 for that stream return no
> + % items. If a call to bulk_get/9 returns `error(...)', all further calls to
> + % get/4, unboxed_get/5 or bulk_get/9 for that stream return an error,
> + % although not necessarily the same one.
> %
> pred bulk_get(Stream::in, Index::in, int::in,
> Store::bulk_get_di, Store::bulk_get_uo,
> _______________________________________________
> reviews mailing list
> reviews at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/reviews
More information about the reviews
mailing list