[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