Traditional Prolog provides limited support for text input-output through the
notions of a "current input" and "current output" stream. All input
operations read from the current input stream, and all output operations
write to the current output stream. These streams are initially bound
to the interactive console, but can be reassigned to a disk file through the
use of the built-in predicates see/1 and tell/1.
The ISO standard includes the notion of an IO stream, and provides
IO predicates that take a first argument which specifies the stream on which
the operation is to be performed. Streams are first-class terms, and can be
bound to variables (in fact, open/3, 4 do precisely this).
In addition, a stream can have any number of aliases, which are ordinary atoms.
When a stream must be specified as an argument to a built-in predicate,
either the stream term created by open/3, 4, or an alias can be used.
For compatibility with traditional Prolog, ISO Prolog also provides versions of its IO predicates that take one less parameter, and implicitly read from a default current input stream or write to a default current output stream as the case may be. However, there are some minor differences between the mechanisms found in traditional Prolog and the backward compatibility support present in ISO Prolog, including the following:
| Traditional Prolog predicate | ISO Prolog predicate |
|---|---|
see/1 | open/3, 4set_input/1(see below) |
seeing/1 | current_input/1 |
seen/0 | close/1, 2 |
tell/1 | open/3, 4set_output/1(see below) |
telling/1 | current_output/1 |
told/1 | close/1, 2 |
see/1 and tell/1 can
be used either to open a new stream or to resume using a
previously opened stream - the distinction being made by whether or not
a stream of that name is currently open. ISO Prolog provides
separate mechanisms for opening a stream (open/3, 4)
and for making a stream the default input or output stream
(set_input/1 and set_output/1).
seeing/1 or telling/1.
Traditional Prolog does not have any notion of a stream term or an
alias.
user for the interactive
console for see/1, seeing/1, tell/1,
and telling/1, as well as consult/1 and
reconsult/1. ISO Prolog uses the names user_input
and user_output.
| Traditional Prolog predicate | ISO Prolog predicate |
|---|---|
| (No equivalent) | at_end_of_stream/0 |
display/1 | write_canonical/1 |
| (No equivalent) | flush_output/0 |
get/1 | (No equivalent) |
| (No equivalent) | get_char/1 |
get0/1 | get_code/1 |
nl/0 | nl/0 |
| (No equivalent) | peek_char/1 |
| (No equivalent) | peek_code/1 |
| (No equivalent) | put_char/1 |
put/1 | put_code/1 |
read/1 | read/1 |
| (No equivalent) | read_term/2 |
skip/1 | (No equivalent) |
tab/1 | (No equivalent) |
write/1 | write/1 |
| (No equivalent) | write_term/2 |
writeq/1 | writeq/1 |
PrologJ uses the same stream mechanism as ISO standard Prolog natively. As a result, all the ISO stream operations (including those not discussed above) perform as specified in the ISO standard. When the "traditional" category of built-in predicates is enabled, PrologJ also supports the traditional Prolog stream operations using the exact same predicate names and semantics as traditional Prolog. This implies the following:
see/1 and tell/1 can
be used to open a named stream, or to resume accessing a named stream
(if a stream of that name is already open). In either case, the
specified stream becomes the current input or output stream (as if set
by set_input/1 or set_output/1). When one
of these predicates causes a new stream to be opened, the file name is
made an alias for the resultant stream term. When access to a named
stream that was previously opened by see/1 or
tell/1 is resumed, it picks up where the last access
left off, not at the start of the stream. As an extension, these
predicates can also be used with an alias that was created by
open/4, and cause access to resume at the current position
in the stream.
user is recognized as equivalent to
user_input or user_output with the following
built-in predicates: see/1, tell/1,
consult/1, and reconsult/1, and with lists
typed at the ?- prompt of the interpreter as a shorthand
for consult/reconsult . (The ISO names or an ISO stream term or
alias may be used as well, and the ISO names must be used with
all other built-in predicates).
seeing/1 and telling/1
unify their argument with the file name used to open the current
input or output stream, not with a stream term (or with user
if the current stream is the interactive console). In this respect, their
operation differs from current_input/1 or
current_output/1, which unify with a stream term.
Normally, seeing/1 and telling/1 are used
only with streams opened by see/1 or tell/1.
seen/0 and told/0
are identical to close/1 applied to the current input or
output stream (as the case may be). Note that when close/1
is applied to the current input or output stream, the interactive
console becomes current input or output, as the case may be, so the
ISO and traditional behaviors are the same. Likewise, in both models,
an attempt to close the interactive console is ignored; the predicate
simply succeeds without any changes in the environment.
The normal operation of the traditional input-output predicates is as documented in sections 6.9 or 6.10 of [ Clocksin and Mellish 1994 ]. Error handling uses the same approach as for the ISO predicates. The following table summarizes the error cases for the various input-output predicates which belong to the "Traditional" category.
| Traditional Prolog predicate | Error handling |
|---|---|
display(Term) |
same as write_canonical/1 |
get0(Code) |
same as get_code/1 |
get(Code) |
same as get_code/1 |
put(Code) |
same as put_code/1 |
see(File) |
File is a variable: instantiation_errorFile is neither a variable nor a stream term
nor an atom: type_error(atom, File)The file specified by File does not exist:
existence_error(source_sink, File)The file specified by File cannot be opened:
permission_error(open, source_sink, File)File refers to an existing output stream:
permission_error(input, stream, File)File refers to an existing binary stream:
permission_error(input, binary_stream, File) |
seeing(File) |
File is neither a variable nor an atom:
type_error(atom, File) |
seen |
none |
skip(Code) |
Code is a variable: instantiation_errorCode is neither a variable nor an integer:
type_error(integer, Code)Code is an integer but not an in-character code:
representation_error(in_character_code)The current input stream IS is associated with a binary stream: permission_error(input, binary_stream, IS)The current input stream IS has stream properties end_of_stream(past) and eof_action(error):
permission_error(input, past_end_of_stream, IS)Code does not occur in the stream between the
current position and the end of the stream:
permission_error(input, past_end_of_stream, IS) |
tab(Spaces) |
Spaces is a variable: instantiation_errorSpaces is neither a variable nor an integer:
type_error(integer, Spaces)Spaces is a negative integer:
domain_error(not_less_than_zero, Spaces)The current output stream OS is a binary stream: permission_error(output, binary_stream, OS) |
tell(File) |
File is a variable: instantiation_errorFile is neither a variable nor a stream term
nor an atom: type_error(atom, File)The file specified by File cannot be opened:
permission_error(open, source_sink, File)File refers to an existing input stream:
permission_error(output, stream, File)File refers to an existing binary stream:
permission_error(output, binary_stream, File) |
telling(File) |
File is neither a variable nor an atom:
type_error(atom, File) |
told |
none |
Traditional Prolog defines three predicates allowing the input and output of clauses. PrologJ makes these available when either the "Traditional" or "Clause IO" built-in predicate categories are made available. The documentation below supplements what is provided in [ Clocksin and Mellish 1994 ] sections 6.1 and 6.4.
consult(File)
File is a stream term, an alias for an already open
stream, the atom user, or the specification of a file
that is to be opened. PrologJ assumes that files containing Prolog
code have the extension .pro. If a file name is specified and
this extension is not included, it will be supplied by the system.
File specifies a stream (other than the console) that is
already open, it is reset to its beginning; otherwise a new stream is
created. The specified stream is read as a series of clauses and
directives until end-of-file is encountered. Each clause is asserted
into the database after it is read. At the conclusion of the
operation, if an existing stream (other
than the console) was specified, it is reset to its beginning;
if a stream was newly opened, it is closed.| Conditions | Error Term |
|---|---|
File is a variable |
instantiation_error |
File is neither a variable nor a stream term
nor an atom |
type_error(atom, File) |
The file specified by File does not exist |
existence_error(source_sink, File) |
The file specified by File cannot be opened |
permission_error(open, source_sink, File) |
File refers to an existing output stream |
permission_error(input, stream, File) |
File refers to an existing binary stream |
permission_error(input, binary_stream, File) |
| Some other sort of system error occurs while reading the stream | system_error(system_io_exception) |
listing(Predicate)
Predicate is either an atom or a predicate indicator
pattern; if the former, it is equivalent to atom / _; if
the latter, either the functor or the arity, or both, may be
uninstantiated.enforce_directives flag; if it is on,
only public Prolog predicates are printed; it is is off,
an attempt is made to print all Prolog predicates; however, it is
not possible to print private compiled clauses because the source
form of the head and body of the clause are not preserved in the
compiled code.listing(_/_) is
executed, all (public) predicates defined in Prolog will be
printed.| Conditions | Error Term |
|---|---|
Predicate is a variable |
instantiation_error |
Predicate is neither a variable nor an atom
nor a predicate indicator pattern |
type_error(atom, Predicate) |
Predicate is a predicate indicator pattern, but the
functor component F is neither a variable nor an atom |
type_error(atom, F) |
Predicate is a predicate indicator pattern, but the
arity component A is neither a variable nor an integer |
type_error(integer, A) |
Predicate is a predicate indicator pattern whose
arity component A is a negative integer |
domain_error(not_less_than_zero, A) |
Predicate is a predicate indicator pattern whose
arity component is an integer greater than the maximum permissible
arity for a compound term |
representation_error(max_arity) |
reconsult(File)
File is a stream term, an alias for an already open
stream, the atom user, or the specification of a file
that is to be opened. PrologJ assumes that files containing Prolog
code have the extension .pro. If a file name is specified and
this extension is not included, it will be supplied by the system.
File specifies a stream (other than the console) that is
already open, it is reset to its beginning; otherwise a new stream is
created. The specified stream is read as a series of clauses and
directives until end-of-file is encountered. Each clause is asserted
into the database after it is read. If a clause for an existing predicate
is read, all clauses for that predicate are deleted when the first
new clause is read. At the conclusion of the
operation, if an existing stream (other
than the console) was specified, it is reset to its beginning;
if a stream was newly opened, it is closed.| Conditions | Error Term |
|---|---|
File is a variable |
instantiation_error |
File is neither a variable nor a stream term
nor an atom |
type_error(atom, File) |
The file specified by File does not exist |
existence_error(source_sink, File) |
The file specified by File cannot be opened |
permission_error(open, source_sink, File) |
File refers to an existing output stream |
permission_error(input, stream, File) |
File refers to an existing binary stream |
permission_error(input, binary_stream, File) |
| Some other sort of system error occurs while reading the stream | system_error(system_io_exception) |
As noted above, PrologJ includes a number of input-output predicates that allow the operations of traditional Prolog to be used with ISO-style streams. Each is functionally-equivalent to one of the traditional Prolog input-output predicates, but with an additional first argument that specifies a stream in the same manner as ISO input-output predicates. The following table summarizes the error handling for these predicates:
| Traditional Prolog predicate | Error handling |
|---|---|
display(Stream, Term) |
same as write_canonical/2 |
get0(Stream, Code) |
same as get_code/2 |
get(Stream, Code) |
same as get_code/2 |
put(Stream, Code) |
same as put_code/2 |
listing(Stream, Predicate) |
same as write/2 with regard to the Stream
argumentsame as listing/1 with regard to the Predicate
argument |
skip(Stream, Code) |
same as get_code/2, plusCode is a variable: instantiation_errorCode does not occur in the stream between the
current position and the end of the stream:
permission_error(input, past_end_of_stream, IS) |
tab(Stream, Spaces) |
same as same as put_code/2, plusSpaces is a variable: instantiation_errorSpaces is neither a variable nor an integer:
type_error(integer, Spaces)Spaces is a negative integer:
domain_error(not_less_than_zero, Spaces) |
In the ISO standard, a stream may be created for either read or
write access. (The append option is a variation of
write). However, it is not possible to create a stream that allows
both reading and writing the same stream. PrologJ is extended to allow
specifying the read_write mode when opening a stream - but only
for binary streams. (It is an error to specify the mode read_write
with a text stream. Hence, this mode is only usable with open/4,
since streams not opened without specifying a type option are
text by default.) Both binary read and write operations are
allowed on such a stream. If the stream is also repositionable (which would
normally be the case), it is even possible to read data that had been
previously written to the same stream.
In addition to allowing the three valid write-options described in the ISO
standard (quoted, ignore_ops,
and numbervars), the built-in predicates write_term/2
and write_term/3 also recognized one implementation-specific
option:
escaped(bool) -
bool will be:true - any characters that occur in an atom name which
would need to be escaped by a backslash character in a Java String or
character constant (", ', or \),
will be preceeded by a backslash character - e.g. the atom
name 'wierd"''\\atom' (where the doubling of the
' and \ is required by Prolog syntax) will be
printed as wierd\"\'\\atom, or as
'wierd\"\'\\atom' if quoted(true) is also
specified in the options list.false - no escaping of characters will be done