[m-rev.] IO error type

Peter Wang novalazy at gmail.com
Thu Aug 18 17:24:20 AEST 2022


On Thu, 18 Aug 2022 14:11:05 +1000 Julien Fischer <jfischer at opturion.com> wrote:
> 
> My proposal is as follows:
> 
> 1. We keep the definition of the type system_error/0 as it is, namely:
> 
>      :- type system_error.
>      :- pragma foreign_type(c, system_error, "MR_Integer").
>      :- pragma foreign_type("C#", system_error, "System.Exception").
>      :- pragma foreign_type(java, system_error, "java.lang.Exception").
> 
> (Actually, the Java version probably ought to be java.lang.Throwable,
> but that's a different matter.)
> 
> 2. We export system_error/0 in the documented interface of the io module
>     and also document what its foreign representation is for each backend.
> 
> 3. We redefine io.error to be like the following:
> 
>      :- type io.error
>          --->    io_error_string(string)    % for use by make_io_error/1.
>  	;       io_error_errno(string, system_error)
>          ;       io_error_win_error(string, system_error)
>          ;       io_error_csharp_java_error(string, system_error).
> 
> (At the point we construct these values we will know whether an "int"
> error is an errno or Windows error code.)
> 
> Since io.error now contains the system error we could also omit the
> string in the latter threee cases and only construct it if the user
> requests it.
> 

Ok.

> 4. We can add various semidet functions for classifying and retrieving
> the system_error value, e.g.
> 
>       :- pred io.get_errno_error(io.error::in, system_error::out)
>           is semidet.
>       :- pred io.get_windows_error(io.error::in, system_error::out)
>           is semidet.
> 
> etc. etc.  This provides a mechanism for third-party libraries to get
> the raw error code / exception (and know what kind of error code it is).
> 

Ok.

> 5. We also add the functions you listed below
> 
> >>>    :- pred get_error_name(io.error::in, string::out)
> >>> 	is semidet.
> >>>
> >>> 	% As above, but takes a system_error instead.
> >>> 	%
> >>>    :- pred get_system_error_name(system_error::in, string::out)
> >>> 	is semidet.
> 
> except that the signature of the latter one would be:
> 
>      :- pred get_system_error_name(io.error::in, string::out)
>         is semidet.

Right, if a system_error could be value from multiple sets of errors
then we can't have a predicate that converts an system_error (only) to a
string.

> (I hope there's a way of getting Windows error code name, that doesn't
> involve switching over all 5000 or so Windows error codes; perhaps
> FormatMessage can do that?)
> 

I couldn't find one :(

The MinGW-w64 winerror.h defines ~1765 ERROR_* constants, which should
be far beyond what we need to recognise (practically). Both the switch
for the POSIX and Windows errors would be auto-generated, so it's just a
matter of code size.

> I would prefer not too push large chunks of OS-specific stuff into the
> standard library: that doesn't improve portability, it just means
> programmers have to program around the bits their system doesn't
> support. Examining the different kinds of errors produced by system
> calls is intrinsically a OS-specific thing. The standard library can
> only paper over the difference so far.

I agree with not including too much OS specific functionality in the
standard library. But we provide basic I/O like opening files, deleting
files, etc. and, as it is, the functionality seems incomplete.

Peter


More information about the reviews mailing list