AppliedLogicSystems / ALSProlog

ALS Prolog Compiler & Development Environment
https://alsprolog.com
MIT License
16 stars 9 forks source link

put_atom/2, put_number/3 error in error display #173

Closed kenbowen closed 4 years ago

kenbowen commented 5 years ago

Errors occurring in put_atom/2, put_number/3 error mechanisms:

?- put_atom(user, 3). Error: Argument of type integer expected instead of 3.

Error should be: Argument of type atom expected instead of 3.

?- put_atom(user, 3.4). Error: Argument of type integer expected instead of 3.4.

Error should be: Argument of type atom expected instead of 3.

?- put_number(user,integer,3). Error: Argument of type integer expected instead of 3.

Should not throw error, and should print: 3

?- put_number(user,float,3.4). ??Y@ yes.

Should print: 3.4

chuckhoupt commented 5 years ago

?- put_number(user,integer,3). Should not throw error, and should print: 3

put_number/3's 2nd arg is restricted to byte/short/long/float/double, so anything outside that is a domain error. Here's a proposed test case:

catch(put_number(user, integer, 3), error(domain_error(output_type, integer), _), true),
chuckhoupt commented 5 years ago

?- put_number(user,float,3.4). ??Y@ Should print: 3.4

I think all the put_* preds perform low level output, so put_number/3 outputs raw binary. I.e. 3.4 is output as a 4 byte IEEE encoded float. The ??Y@ is likely correct. Here's a test case for little-endian systems:

( open(string(S), write, O), put_number(O, float, 3.4), close(O), write(S), S == [0'\x9a, 0'\x99, 0'\x59, 0'\x40] ),
kenbowen commented 5 years ago

On Oct 16, 2019, at 3:40 PM, Chuck Houpt notifications@github.com wrote:

?- put_number(user,integer,3). Should not throw error, and should print: 3

put_number/3's 2nd arg is restricted to byte/short/long/float/double, so anything outside that is a domain error.

A case of “seeing" something (“integer") that wasn’t there in the list in the comment before the defn of put_number/3. The first clause simply calls sio_put_number with no change in args, so most certainly — in your next message — you’re right about “...so put_number/3 outputs raw binary”.

Interestingly (grepping), put_number doesn’t occur in builtins or library.

I’ll drop the put_number items from the Issue.
put_atom uses ‘integer' wherever it ought to use ‘atom’:

?-put_atom(user, "abc"). Error: Argument of type integer expected instead of "abc".

?- put_atom(user, f(X)). Error: Argument of type integer expected instead of f(_A).

This appears due to put_atom’s last clause calling put_failure/4, which has this clause:

put_failure(2,Stream,Arg,Call) :- %% SIOEINARG !, curmod(Mod), functor(Call,,LastArg), arg(LastArg,Call,Culprit), type_error(integer, Culprit, [Mod:Call]).

The same problem occurs for put_code and put_char. Changing “integer” to “atom” would make put_atom correct, but still leave put_code, put_char, and put_number incorrect. Now put_failure/4 only occurs in sio.pro in builtins and doesn’t occur in library. So one possibility is to add an argument to put_failure/4, and pass the appropriate constant (atom, char, code, number) in that argument.

Let me know what you think. ——Ken

Here's a proposed test case:

catch(put_number(user, integer, 3), error(domain_error(outputtype, integer), ), true),

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

chuckhoupt commented 5 years ago

Possibly you could distinguish code/char from atom by matching the Call argument. I.e. something like:

put_failure(2,Stream,Arg,put_atom(S, A)) :-
    ...
    type_error(atom, ....).
chuckhoupt commented 5 years ago

For completeness, we should note that put_string/2 also needs exception fixes because it currently just fails instead of correctly throwing instantiation or type errors. For example:

% Should throw type error:
?- put_string(user, foo).
no.