diff: changes to io.m
Fergus Henderson
fjh at cs.mu.oz.au
Thu Apr 24 10:13:03 AEST 1997
Hi Tom,
Can you please review this one?
-----------------------------------------------------------------------------
Implement io__print. Improvements to io__write and io__read.
Add stubs for io__read_binary and io__write_binary.
library/io.m:
Change the implementation of `io__write':
- it now writes out terms using list syntax and infix notation
when appropriate, just like term_io__write_term
(but like term_io__write_term, it doesn't yet take operator
precedence into account, so it still outputs some redundant
parentheses)
- it properly quotes and escapes strings, characters, and atoms
(XXX but it does not yet properly parenthesize constants that
happen to have the same name as an operator)
Add `io__print'. This is similar to `io__write', except that
if the argument is a single string or character, it is printed
directly, rather than inside quotes with special characters escaped.
Rename `io__read_anything' as `io__read', and improve the error
messages slightly. The implementation is still dependent on
term_to_type which is not yet implemented.
Add `io__write_binary' and `io__read_binary'. (The current
implementation is just a pair of stubs that call `io__write'
and `io__read'; that works, but it kinda defeats the purpose...)
Provide reasonable documentation for all of the above.
For backwards compatibility with previous versions of Mercury,
add versions of `io__read_anything' and `io__write_anything'
that just call `io__read' and `io__write' respectively,
but declare them as `pragma obsolete'.
Index: io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.116
diff -u -r1.116 io.m
--- io.m 1997/04/21 03:34:05 1.116
+++ io.m 1997/04/23 23:55:38
@@ -1,5 +1,5 @@
%-----------------------------------------------------------------------------%
-% Copyright (C) 1995 University of Melbourne.
+% Copyright (C) 1993-1997 University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%-----------------------------------------------------------------------------%
@@ -71,6 +71,7 @@
:- type io__read_result(T) ---> ok(T)
; eof
; error(string, int).
+ % error message, line number
:- type io__error. % Use io__error_message to decode it.
@@ -128,22 +129,24 @@
% You can put back as many characters as you like.
% You can even put back something that you didn't actually read.
-:- pred io__read_anything(io__read_result(T), io__state, io__state).
-:- mode io__read_anything(out, di, uo) is det.
-% Reads its argument from the current input stream.
-% The argument may be of (almost) any type.
-% The term read had better be of the right type!
-% XXX io__read_anything is NOT YET IMPLEMENTED.
-% It will also probably be renamed io__read.
-
-:- pred io__read_anything(io__input_stream, io__read_result(T),
- io__state, io__state).
-:- mode io__read_anything(in, out, di, uo) is det.
-% Reads its argument to the specified stream.
-% The argument may be of (almost) any type.
-% The term read had better be of the right type!
-% XXX io__read_anything is NOT YET IMPLEMENTED.
-% It will also probably be renamed io__read.
+:- pred io__read(io__read_result(T), io__state, io__state).
+:- mode io__read(out, di, uo) is det.
+:- pred io__read(io__input_stream, io__read_result(T), io__state, io__state).
+:- mode io__read(in, out, di, uo) is det.
+% Reads a ground term of any type, written using standard
+% Mercury syntax, from the current or specified input stream.
+% The type of the term read is determined by the context
+% in which `io__read' is used.
+% If there are no more non-whitespace characters before the
+% end of file, then `io__read' returns `eof'.
+% If it can read in a syntactically correct ground term
+% of the correct type, then it returns `ok(Term)'.
+% If characters on the input stream (up to the next `.' that
+% is followed by whitespace) do not form a syntactically
+% correct term, or if the term read is not a ground term,
+% if the term is not a valid term of the appropriate type,
+% or if encounters an I/O error, then it returns
+% `error(Message, LineNumber)'.
:- pred io__ignore_whitespace(io__result, io__state, io__state).
:- mode io__ignore_whitespace(out, di, uo) is det.
@@ -160,6 +163,43 @@
% Text output predicates.
+:- pred io__print(T, io__state, io__state).
+:- mode io__print(in, di, uo) is det.
+:- pred io__print(io__output_stream, T, io__state, io__state).
+:- mode io__print(in, in, di, uo) is det.
+% io__print/3 writes its argument to the current output stream.
+% io__print/4 writes its argument to the specified output
+% stream. In either case, the argument may be of any type.
+% The argument is written in a format that is intended to
+% be human-readable.
+%
+% If the argument is just a single string or character, it
+% will be printed out exactly as is (unquoted).
+% For higher-order types, or for types defined using the
+% foreign language interface (pragma c_code), the text output
+% will only describe the type that is being printed, not the
+% value.
+
+:- pred io__write(T, io__state, io__state).
+:- mode io__write(in, di, uo) is det.
+:- pred io__write(io__output_stream, T, io__state, io__state).
+:- mode io__write(in, in, di, uo) is det.
+% io__write/3 writes its argument to the current output stream.
+% io__write/4 writes its argument to the specified output stream.
+% The argument may be of any type.
+% The argument is written in a format that is intended to
+% be valid Mercury syntax whenever possible.
+%
+% Strings and characters are always printed out in quotes,
+% using backslash escapes if necessary.
+% For higher-order types, or for types defined using the
+% foreign language interface (pragma c_code), the text output
+% will only describe the type that is being printed, not the
+% value, and the result may not be parsable by io__read.
+% But in all other cases the format used is standard Mercury
+% syntax, and if you do append a period and newline (".\n"),
+% then the results can be read in again using `io__read'.
+
:- pred io__nl(io__state, io__state).
:- mode io__nl(di, uo) is det.
% Writes a newline character to the current output stream.
@@ -174,7 +214,7 @@
:- pred io__write_string(io__output_stream, string, io__state, io__state).
:- mode io__write_string(in, in, di, uo) is det.
-% Writes a string to the specified stream.
+% Writes a string to the specified output stream.
:- pred io__write_strings(list(string), io__state, io__state).
:- mode io__write_strings(in, di, uo) is det.
@@ -183,7 +223,7 @@
:- pred io__write_strings(io__output_stream, list(string),
io__state, io__state).
:- mode io__write_strings(in, in, di, uo) is det.
-% Writes a string to the specified stream.
+% Writes a list of strings to the specified output stream.
:- pred io__write_char(char, io__state, io__state).
:- mode io__write_char(in, di, uo) is det.
@@ -191,7 +231,7 @@
:- pred io__write_char(io__output_stream, char, io__state, io__state).
:- mode io__write_char(in, in, di, uo) is det.
-% Writes a character to the specified stream.
+% Writes a character to the specified output stream.
:- pred io__write_int(int, io__state, io__state).
:- mode io__write_int(in, di, uo) is det.
@@ -199,7 +239,7 @@
:- pred io__write_int(io__output_stream, int, io__state, io__state).
:- mode io__write_int(in, in, di, uo) is det.
-% Writes an integer to the specified stream.
+% Writes an integer to the specified output stream.
:- pred io__write_float(float, io__state, io__state).
:- mode io__write_float(in, di, uo) is det.
@@ -209,14 +249,14 @@
:- pred io__write_float(io__output_stream, float, io__state, io__state).
:- mode io__write_float(in, in, di, uo) is det.
% io__write_float(Float, IO0, IO1).
-% Writes a floating point number to the specified stream.
+% Writes a floating point number to the specified output stream.
:- pred io__format(string, list(io__poly_type), io__state, io__state).
:- mode io__format(in, in, di, uo) is det.
% io__format(FormatString, Arguments, IO0, IO).
% Formats the specified arguments according to
% the format string, using string__format, and
-% then writes the result to standard output.
+% then writes the result to the current output stream.
% (See the documentation of string__format for details.)
:- pred io__format(io__output_stream, string, list(io__poly_type),
@@ -233,25 +273,11 @@
% io__write_many(Arguments, IO0, IO).
% Writes the specified arguments to the current output stream.
-:- pred io__write_many(io__output_stream, list(io__poly_type), io__state, io__state).
+:- pred io__write_many(io__output_stream, list(io__poly_type),
+ io__state, io__state).
:- mode io__write_many(in, in, di, uo) is det.
% io__write_many(Stream, Arguments, IO0, IO).
-% Writes the specified arguments to the specified stream.
-
-:- pred io__write(T, io__state, io__state).
-:- mode io__write(in, di, uo) is det.
-% Writes its argument to the current output stream.
-% The argument may be of (almost) any type.
-% (Any type except a higher-order predicate type,
-% or some of the builtin types such as io__state itself.)
-% XXX Not all quoting of atoms is done correctly.
-
-:- pred io__write(io__output_stream, T, io__state, io__state).
-:- mode io__write(in, in, di, uo) is det.
-% Writes its argument to the specified stream.
-% The argument may be of (almost) any type.
-% (Any type except a higher-order predicate type,
-% or some of the builtin types such as io__state itself.)
+% Writes the specified arguments to the specified output stream.
:- pred io__write_list(list(T), string, pred(T, io__state, io__state),
io__state, io__state).
@@ -291,7 +317,8 @@
% Closes the current input stream.
% The current input stream reverts to standard input.
-:- pred io__open_input(string, io__res(io__input_stream), io__state, io__state).
+:- pred io__open_input(string, io__res(io__input_stream),
+ io__state, io__state).
:- mode io__open_input(in, out, di, uo) is det.
% io__open_input(File, Result, IO0, IO1).
% Attempts to open a file for input.
@@ -454,16 +481,33 @@
% Binary input predicates.
+:- pred io__read_binary(io__result(T), io__state, io__state).
+:- mode io__read_binary(out, di, uo) is det.
+% Reads a binary representation of a term of type T
+% from the current binary input stream.
+
+:- pred io__read_binary(io__binary_input_stream, io__result(T),
+ io__state, io__state).
+:- mode io__read_binary(in, out, di, uo) is det.
+% Reads a binary representation of a term of type T
+% from the specified binary input stream.
+
+% Note: if you attempt to read a binary representation written
+% by a different program, or a different version of the same
+% program, then the results are not guaranteed to be meaningful.
+% Another caveat is that higher-order types cannot be read.
+% (If you try, you will get a runtime error.)
+
:- pred io__read_byte(io__result(int), io__state, io__state).
:- mode io__read_byte(out, di, uo) is det.
-% Reads a single byte from the current binary input
-% stream and returns it in the bottom 8 bits of an integer.
+% Reads a single 8-bit byte from the current binary input
+% stream.
:- pred io__read_byte(io__binary_input_stream, io__result(int),
io__state, io__state).
:- mode io__read_byte(in, out, di, uo) is det.
-% Reads a single byte from the specified binary input
-% stream and returns it in the bottom 8 bits of an integer.
+% Reads a single 8-bit byte from the specified binary input
+% stream.
:- pred io__putback_byte(int, io__state, io__state).
:- mode io__putback_byte(in, di, uo) is det.
@@ -485,6 +529,18 @@
% XXX what about wide characters?
+:- pred io__write_binary(T, io__state, io__state).
+:- mode io__write_binary(in, di, uo) is det.
+% Writes a binary representation of a term to the current
+% binary output stream, in a format suitable for reading
+% in again with io__read_binary.
+
+:- pred io__write_binary(io__binary_output_stream, T, io__state, io__state).
+:- mode io__write_binary(in, in, di, uo) is det.
+% Writes a binary representation of a term to the specified
+% binary output stream, in a format suitable for reading
+% in again with io__read_binary.
+
:- pred io__write_byte(int, io__state, io__state).
:- mode io__write_byte(in, di, uo) is det.
% Writes a single byte to the current binary output stream.
@@ -718,7 +774,6 @@
:- pred io__remove_file(string, io__res, io__state, io__state).
:- mode io__remove_file(in, out, di, uo) is det.
-
%-----------------------------------------------------------------------------%
% Memory management predicates.
@@ -759,6 +814,36 @@
% code.
%-----------------------------------------------------------------------------%
+:- implementation.
+
+% Everything below here is not intended to be part of the public interface,
+% and will not be included in the Mercury library reference manual.
+
+%-----------------------------------------------------------------------------%
+:- interface.
+
+% For backwards compatibility:
+
+:- pragma obsolete(io__read_anything/3).
+:- pred io__read_anything(io__read_result(T), io__state, io__state).
+:- mode io__read_anything(out, di, uo) is det.
+% Same as io__read/3.
+
+:- pragma obsolete(io__read_anything/4).
+:- pred io__read_anything(io__output_stream, io__read_result(T),
+ io__state, io__state).
+:- mode io__read_anything(in, out, di, uo) is det.
+% Same as io__read/4.
+
+:- pragma obsolete(io__write_anything/3).
+:- pred io__write_anything(T, io__state, io__state).
+:- mode io__write_anything(in, di, uo) is det.
+% Same as io__write/3.
+
+:- pragma obsolete(io__write_anything/4).
+:- pred io__write_anything(io__output_stream, T, io__state, io__state).
+:- mode io__write_anything(in, in, di, uo) is det.
+% Same as io__write/4.
% For use by term_io.m:
@@ -781,7 +866,7 @@
%-----------------------------------------------------------------------------%
:- implementation.
-:- import_module map, dir, term_io, varset, require, time.
+:- import_module map, dir, term, term_io, varset, require, time, uniq_array.
:- type io__state
---> io__state(
@@ -986,25 +1071,37 @@
io__binary_input_stream(Stream),
io__putback_byte(Stream, Char).
-io__read_anything(X) -->
+io__read_anything(Result) -->
+ io__read(Result).
+
+io__read(Result) -->
term_io__read_term(ReadResult),
- ( { ReadResult = term(_VarSet, Term) },
+ (
+ { ReadResult = term(_VarSet, Term) },
( { term_to_type(Term, Type) } ->
- { X = ok(Type) }
+ { Result = ok(Type) }
;
- { X = error("io__read_anything : the term read was not a valid type", 0) }
+ io__get_line_number(LineNumber),
+ ( { \+ term__is_ground(Term) } ->
+ { Result = error("io__read: the term read was not a ground term", LineNumber) }
+ ;
+ { Result = error("io__read: the term read did not have the right type", LineNumber) }
+ )
)
;
{ ReadResult = eof },
- { X = eof }
+ { Result = eof }
;
{ ReadResult = error(String, Int) },
- { X = error(String, Int) }
+ { Result = error(String, Int) }
).
-io__read_anything(Stream, X) -->
+io__read_anything(Stream, Result) -->
+ io__read(Stream, Result).
+
+io__read(Stream, Result) -->
io__set_input_stream(Stream, OrigStream),
- io__read_anything(X),
+ io__read(Result),
io__set_input_stream(OrigStream, _Stream).
io__ignore_whitespace(Result) -->
@@ -1076,37 +1173,197 @@
io__write_float(Stream, F),
io__write_many(Stream, Rest).
+io__print(Stream, Term) -->
+ io__set_output_stream(Stream, OrigStream),
+ io__print(Term),
+ io__set_output_stream(OrigStream, _Stream).
+
+io__print(Term) -->
+ % `string' and `char' are special cases for io__print
+ { type_to_univ(Term, Univ) },
+ ( { univ_to_type(Univ, String) } ->
+ io__write_string(String)
+ ; { univ_to_type(Univ, Char) } ->
+ io__write_char(Char)
+ ;
+ io__print_quoted(Term)
+ ).
+
+:- pred io__print_quoted(T, io__state, io__state).
+:- mode io__print_quoted(in, di, uo) is det.
+
+io__print_quoted(Term) -->
+ io__write(Term).
+/*
+When we have type classes, then instead of io__write(Term),
+we will want to do something like
+ ( { univ_to_type_class(Univ, Portrayable) } ->
+ portray(Portrayable)
+ ;
+ ... code like io__write, but which prints
+ the arguments using io__print_quoted, rather than
+ io__write ...
+ )
+*/
+
+io__write_anything(Anything) -->
+ io__write(Anything).
+
+io__write_anything(Stream, Anything) -->
+ io__write(Stream, Anything).
+
io__write(Stream, X) -->
io__set_output_stream(Stream, OrigStream),
io__write(X),
io__set_output_stream(OrigStream, _Stream).
+io__write(Term) -->
+ % we need to special-case the builtin types:
+ % int, char, float, string
+ % type_info, univ, uniq_array, c_pointer
+ { type_to_univ(Term, Univ) },
+ ( { univ_to_type(Univ, String) } ->
+ term_io__quote_string(String)
+ ; { univ_to_type(Univ, Char) } ->
+ term_io__quote_char(Char)
+ ; { univ_to_type(Univ, Int) } ->
+ io__write_int(Int)
+ ; { univ_to_type(Univ, Float) } ->
+ io__write_float(Float)
+% XXX the following code doesn't work, because we can't use
+% univ_to_type to match on a non-ground type `uniq_array(T)'.
+% ; { univ_to_type(Univ, UniqArray) } ->
+% io__write_uniq_array(UniqArray)
+ ; { univ_to_type(Univ, TypeInfo) } ->
+ io__write_string(type_name(TypeInfo))
+ ;
+ io__write_term(Term)
+ ),
+ % append type qualifier, if the original value was of type univ
+ ( { type_of(Term) = type_of(Univ) } ->
+ io__write_string(" : "), % XXX TYPE_QUAL_OP
+ io__write(type_of(Term))
+ ;
+ []
+ ).
+
+:- pred io__write_uniq_array(uniq_array(T), io__state, io__state).
+:- mode io__write_uniq_array(in, di, uo) is det.
+io__write_uniq_array(UniqArray) -->
+ io__write_string("uniq_array("),
+ { uniq_array__to_list(UniqArray, List) },
+ io__write(List),
+ io__write_string(")").
-% We want to call io__write_args as a tail-call, and so that we only
-% put one stack frame up per level of traversal.
-% This is why the code is a little unusual.
-
-io__write(Anything) -->
- { expand(Anything, Functor, _Arity, Args) },
- io__write_string(Functor),
+:- pred io__write_term(T, io__state, io__state).
+:- mode io__write_term(in, di, uo) is det.
+
+io__write_term(Term) -->
+ { expand(Term, Functor, _Arity, Args) },
+ io__get_op_table(OpTable),
(
- { Args = [Arg | Args1] }
+ { Functor = "." },
+ { Args = [ListHead, ListTail] }
+ ->
+ io__write_char('['),
+ io__write(ListHead),
+ io__write_list_tail(ListTail),
+ io__write_char(']')
+ ;
+ { Functor = "[]" },
+ { Args = [] }
+ ->
+ io__write_string("[]")
+ ;
+ { Functor = "{}" },
+ { Args = [BracedTerm] }
+ ->
+ io__write_string("{ "),
+ io__write(BracedTerm),
+ io__write_string(" }")
+ ;
+ { Args = [PrefixArg] },
+ { ops__lookup_prefix_op(OpTable, Functor, _, _) }
+ ->
+ io__write_char('('),
+ term_io__quote_atom(Functor),
+ io__write_char(' '),
+ io__write(PrefixArg),
+ io__write_char(')')
+ ;
+ { Args = [PostfixArg] },
+ { ops__lookup_postfix_op(OpTable, Functor, _, _) }
+ ->
+ io__write_char('('),
+ io__write(PostfixArg),
+ io__write_char(' '),
+ term_io__quote_atom(Functor),
+ io__write_char(')')
+ ;
+ { Args = [Arg1, Arg2] },
+ { ops__lookup_infix_op(OpTable, Functor, _, _, _) }
+ ->
+ io__write_char('('),
+ io__write(Arg1),
+ io__write_char(' '),
+ term_io__quote_atom(Functor),
+ io__write_char(' '),
+ io__write(Arg2),
+ io__write_char(')')
+ ;
+ { Args = [Arg1, Arg2] },
+ { ops__lookup_binary_prefix_op(OpTable, Functor, _, _, _) }
->
- io__write_string("("),
- io__write(Arg),
- io__write_args(Args1)
+ io__write_char('('),
+ term_io__quote_atom(Functor),
+ io__write_char(' '),
+ io__write(Arg1),
+ io__write_char(' '),
+ io__write(Arg2),
+ io__write_char(')')
;
+ term_io__quote_atom(Functor),
+ (
+ { Args = [X|Xs] }
+ ->
+ io__write_char('('),
+ io__write(X),
+ io__write_term_args(Xs),
+ io__write_char(')')
+ ;
+ []
+ )
+ ).
+
+:- pred io__write_list_tail(univ, io__state, io__state).
+:- mode io__write_list_tail(in, di, uo) is det.
+
+io__write_list_tail(Term) -->
+ (
+ { expand(Term, ".", _Arity, [ListHead, ListTail]) }
+ ->
+ io__write_string(", "),
+ io__write(ListHead),
+ io__write_list_tail(ListTail)
+ ;
+ { expand(Term, "[]", _Arity, []) }
+ ->
[]
+ ;
+ io__write_string(" | "),
+ io__write(Term)
).
-:- pred io__write_args(list(univ)::in, io__state::di, io__state::uo) is det.
-io__write_args([]) -->
- io__write_string(")").
-io__write_args([Arg | Args]) -->
+:- pred io__write_term_args(list(univ), io__state, io__state).
+:- mode io__write_term_args(in, di, uo) is det.
+
+ % write the remaining arguments
+io__write_term_args([]) --> [].
+io__write_term_args([X|Xs]) -->
io__write_string(", "),
- io__write(Arg),
- io__write_args(Args).
+ io__write(X),
+ io__write_term_args(Xs).
%-----------------------------------------------------------------------------%
@@ -1125,6 +1382,39 @@
io__set_output_stream(Stream, OrigStream),
io__write_list(List, Separator, OutputPred),
io__set_output_stream(OrigStream, _Stream).
+
+%-----------------------------------------------------------------------------%
+
+io__write_binary(Stream, Term) -->
+ io__set_binary_output_stream(Stream, OrigStream),
+ io__write_binary(Term),
+ io__set_binary_output_stream(OrigStream, _Stream).
+
+io__read_binary(Stream, Result) -->
+ io__set_output_stream(Stream, OrigStream),
+ io__read_binary(Result),
+ io__set_output_stream(OrigStream, _Stream).
+
+io__write_binary(Term) -->
+ % a quick-and-dirty implementation... not very space-efficient
+ % (not really binary!)
+ io__binary_output_stream(Stream),
+ io__write(Stream, Term),
+ io__write_string(Stream, ".\n").
+
+io__read_binary(Result) -->
+ % a quick-and-dirty implementation... not very space-efficient
+ % (not really binary!)
+ io__binary_input_stream(Stream),
+ io__read(Stream, ReadResult),
+ { io__convert_read_result(ReadResult, Result) }.
+
+:- pred io__convert_read_result(io__read_result(T), io__result(T)).
+:- mode io__convert_read_result(in, out) is det.
+
+io__convert_read_result(ok(T), ok(T)).
+io__convert_read_result(eof, eof).
+io__convert_read_result(error(Error, _Line), error(Error)).
%-----------------------------------------------------------------------------%
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list