[m-users.] io.error type

Volker Wysk post at volker-wysk.de
Sat Feb 5 18:06:53 AEDT 2022


Am Samstag, dem 05.02.2022 um 17:19 +1100 schrieb Peter Wang:
> On Sat, 05 Feb 2022 13:51:58 +1100 Julien Fischer <jfischer at opturion.com> wrote:
> > Hi Peter,
> > 
> > On Sat, 5 Feb 2022, Peter Wang wrote:
> > 
> > > On Fri, 04 Feb 2022 15:52:38 +0100 Volker Wysk <post at volker-wysk.de> wrote:
> > > > Am Freitag, dem 04.02.2022 um 12:54 +0100 schrieb Fabrice Nicol:
> > > > > So yes, errno codes could have been returned, if is_error had been 
> > > > > publicly visible, but design decisions went against this.
> > > > 
> > > > How are the chances that this will be changed? Not being able to determine
> > > > which error occured, is kind of grave.
> > > 
> > > I agree it would sometimes be useful to get a machine-usable reason for
> > > an error. I think we should add something like:
> > > 
> > >        % Get a system-specific error code associated with an error,
> > >        % if any. On C backends, the error code should be an errno
> > >        % value.
> > >        %
> > >    :- pred system_error_code(io.error::in, int::out) is semidet.
> > 
> > My inclination would be to just to store the system_error value in the
> > io.error type, rather than turning into an int.  If we document
> > what the target language representation of a system_error value is,
> > then it will be "helpful" for the C# and Java backends as well.
> > 
> > (The io.error type would continue to contain its current string field,
> > since removing it would break code that calls io.error_message.)
> 
> Yes, that seems better. So we have:
> 
>     % implementation
>     :- type io.error
>         --->    io_error(system_error, string).
> 
>     :- func make_io_error(system_error, string) = io.error.
> 
>     :- pred get_system_error(io.error::in, system_error::out)
>         is semidet.
> 
> An io.error value constructed by make_io_error/1 will have a dummy
> system_error in the first argument; it can be -1 or null.

I think that an enumeration type for the possible POSIX error codes is
needed. You can't just use an integer value, because those are platform
dependent. They're C macros, and, AFAIK, it isn't guaranteed that they are
defined to be the same number on each platform.

This has already been done in extras/posix/posix.m, so it could just be
copied from there:

:- type error
    --->    e2BIG           /* Arg list too long */
    ;       eACCES          /* Permission denied */
    ;       eAGAIN          /* Try again */
(...)

:- pred errno(posix.error::out, io::di, io::uo) is det.

    % Get the numerical value of an errno on the C side, from the error
    % enumeration "posix.error" on the Mercury side. This always succeeds. 
    % This is needed when you want to do something with an errno value in 
    % foreign code, such as in strerror().
    %
:- pred error_to_cerrno(posix.error::in, int::out) is det.

(...)

:- pred num_error(int, posix.error).
:- mode num_error(in, out) is semidet.
:- mode num_error(out, in) is semidet.

num_error(Num, Err) :-
    (   Num = 0,    Err = e2BIG
    ;   Num = 1,    Err = eACCES
(...)

:- func cerrno_to_num(int) = int.

:- pragma foreign_proc("C",
    cerrno_to_num(Er::in) = (En::out),
    [promise_pure, will_not_call_mercury, thread_safe],
"
    switch (Er) {
        case E2BIG:     En = 0;     break;
        case EACCES:    En = 1;     break;
        case EAGAIN:    En = 2;     break;
(...)


Cheers, Volker
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.mercurylang.org/archives/users/attachments/20220205/fdf9b51e/attachment.sig>


More information about the users mailing list