[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