[m-users.] io.error type

Julien Fischer jfischer at opturion.com
Sat Feb 5 19:36:32 AEDT 2022



On Sat, 5 Feb 2022, Volker Wysk wrote:

> 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 cannot assume that the system_error values correspond to POSIX error
codes at all.  The situation on Windows is (as usual) overly
complicated: Windows has its own system error codes, which *some* library
functions map into a subset of the POSIX error codes.

In any case, the above is all very C-specific and doesn't make much
sense of either Java or C#.

I think the most the standard library should do is provide you with
access to the raw error value.  If you want to do something with that,
then you do so on the understanding that whatever you are doing is
necessarily system dependent.

> 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 */

(Incidently, I would note that type is *not* an enumeration; it can't be
because it has to handle the case where the error code is not
recognised.  Most Unix-like systems define error codes additional to
those specified in POSIX.)

> (...)
>
> :- 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.

Once io.system_error is in the public interface of the io module,
there'd be no reason not to add:

     :- func system_error_to_posix_error(system_error) = error.

to the POSIX binding.

Julien.


More information about the users mailing list