Used to define all printing in Shen, is 'write-byte' which takes a byte and a sink S and writes the byte to S.
Higher level is 'pr' which takes a string and a stream and prints the string to the stream and returns the string.
If the stream argument in either case is omitted then the stream defaults to standard output.
'print' prints its argument exactly as it appears and returns that argument, 'output' prints a string using slots
if needed and returns a string. Note in Shen, the slot ˜S is supported as well as ˜A. The effect of ˜S
(as in Common Lisp) is that string quoting is preserved. ˜% forces a new line. Thus (output "˜A" "hello there")
prints 'hello there' but '(output "˜S" "hello there")' prints "hello there".
Note that 'output' returns a string as a value which is the same string that it prints.
Shen provides an extra formatting command ˜R, which prints the argument using ()s rather than s, which is useful
for printing logical and mathematical formulae.
All three functions depend on 'make-string' which builds a string from a template and a series of arguments. Thus
(make-string "˜A loves ˜A and ˜A" John Mary Tim) returns "John loves Mary and Tim". Use 'make-string' to coerce
an arbitrary object into a string. To write to a stream, you can use 'pr' and 'make-string' combined as in
(pr (make-string "˜A loves ˜A and ˜A" John Mary Tim) ).
There is also a function (nl N) which prints off N new lines and returns zero. If the argument is omitted,
then (nl) prints off a single new line.
Note that 'print', 'error', 'output' and 'make-string' are all polyadic and that therefore they are syntactic fictions
which are represented by internal functions of a fixed arity.
Vectors and lists are printed off using <...>. The vector whose elements from address 1 to the end are 1, 2
and 3 is printed off as <1 2 3>. Vectors or lists of more than 20 elements have the remaining elements printed
off under 'etc' e.g a standard vector of the first 100 positive integers would be printed off as
<1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... etc>
The global *maximum-print-sequence-size* controls this feature and should always be set to a positive whole
Non-standard vectors are printed off in a special manner. For example, in porting Shen to a platform which
lacked symbols as a basic datatype, the programmer can define symbol as a new immutable datatype comprised
of a non-standard vector whose zeroth address holds a tag indicating that the vector represents a symbol and
whose first address holds a string representing the symbol.
In this case the programmer can indicate in the non-standard vector itself how the object is supposed to be
printed off by making the tag into a print function. This is called a print vector in Shen. Thus the representation
of the tuple (@p a b) in Shen is:
| address 0 || address 1 || address 2 |
tuple || a || b |
The Shen printer, when confronted with a non-standard vector V whose 0th address contains a symbol F where
(fn F) is defined, uses F as as a formatting function - the function that determines how the non-standard vector is printed. This
formatting function tells Shen how the print representation of V is to be bundled into the string which is eventually
printed off and hence how that print vector will appear when printed. Hence the tuple function will map the tuple
to a string. In Shen it is defined as follows.
X -> (make-string "(@p ˜S ˜S)" (fst X) (snd X)))
If the 0th address of a non-standard vector is not occupied by a symbol F where (fn F) is defined then
the 0th element is printed and the vector is printed as a standard vector except << ... >> is used instead of < ... >.
The print representation of the failure object is ... (three dots).
The global variable *hush* is set by default to false. If set to true then all messages printed from output and
print are disabled, through messages using pr will still be printed to the target stream. Effectively this disables
system reports from Shen and all printing is then driven by the user. This feature was suggested by Ramil
Farkshatov as an aid to diagnostics.
The functions 'lineread', 'input', 'input+', 'read' are in part adapted from Qi where they were all fixed to standard
input. In version 13 of Shen these were made polyadic and relativised to an input stream. If no stream is chosen then Shen
chooses standard input. The qualities of these functions are as follows.
'lineread' reads in a line of Shen tokens terminated by a new line.
'read' reads the first available Shen token
'input' reads the first available Shen token and evaluates it returning a normal form
'input+' receives a type T and a stream S and reads the first token off S, evaluates it and returns the normal form
if that token is of type T. If the token is not of type T then an error is returned. Note that after Shen 13,
(input+ : number) is just written as (input+ number).
All these functions return an error empty stream if the stream is empty.