She puzzled over this for some time, but at last a bright thought struck her. "Why, it's a Looking-glass book, of course! And, if I hold it up to a glass, the words will all go the right way again."
In which we try to remedy the fact that, due to I/O limitations, INTERCAL can not even in principle perform the same tasks as other languages. It is hoped that this addition will permit INTERCAL users to waste vast quantities of computer time well into the 21st century.
One of the goals of INTERCAL was to provide a language which, though different from all other languages, is nevertheless theoretically capable of all the same tasks. INTERCAL-72 failed to accomplish this because its I/O functions could not handle arbitrary streams of bits, or even arbitrary sequences of characters. A language which can't even send its input directly to its output can hardly be considered as capable as other languages.
To remedy this problem, character I/O is now provided in a form based
on the "Turing Text" model, originally proposed by Jon Blow. The
C-INTERCAL programmer can access this capability by placing a
one-dimensional array in the list of items given to a
READ OUT statement. On execution of the
statement, the elements of the array will, from first to last, be
either loaded from the input or sent to the output, as appropriate, in
the manner described below. There is currently no support for I/O
involving higher-dimensional arrays, but some form of graphics might
be a possible 2-D interpretation.
The heart of the Turing Text model is the idea of a continuous loop of tape containing, in order, all the characters in the machine's character set. When a character is received by the input routine, the tape is advanced the appropriate number of spaces to bring that character under the tape head, and the number of spaces the tape was moved is the number that is actually seen by the INTERCAL program. Another way to say this is that the number placed in an INTERCAL array is the difference between the character just received and the previous character, modulo the number of characters in the machine character set.
Output works in just the opposite fashion, except that the characters being output come from the other side of the tape. From this position the characters on the tape appear to be in reverse order, and are individually backwards as well. (We would show you what it looks like, but we don't have a font with backwards letters available. Use your imagination.) The effect is that a number is taken out of an INTERCAL array, subtracted from the last character outupt--i.e., the result of the last subtraction--and then sent on down the output channel. The only catch is that the character as seen by the INTERCAL program is the mirror mirror-image of the character as seen by the machine and the user. The bits of the character are therefore taken in reverse order as it is sent to the output. Note that this bit reversal affects only the character seen by the outside world; it does not affect the character stored internally by the program, from which the next output number will be subtracted. All subtractions are done modulo the number of characters in the character set.
Two different tapes are used for input and output to allow for future expansion of the language to include multiple input and output channels. Both tapes start at character 0 when a program begins execution. On input, when an end-of-file marker is reached the number placed in the array is one greater than the highest-numbered character on the tape.
If all this seems terribly complicated, it should be made perfectly clear by the following example program, which simply maps its input to its output (like a simplified UNIX cat). It assumes that characters are 8 bits long, but that's fine since the current version of C-INTERCAL does too. It uses the standard library routines for addition and subtraction.
DO ,1 <- #1 DO .4 <- #0 DO .5 <- #0 DO COME FROM (30) DO WRITE IN ,1 DO .1 <- ,1SUB#1 DO (10) NEXT PLEASE GIVE UP (20) PLEASE RESUME '?.1$#256'~'#256$#256' (10) DO (20) NEXT DO FORGET #1 DO .2 <- .4 DO (1000) NEXT DO .4 <- .3~#255 DO .3 <- !3~#15'$!3~#240' DO .3 <- !3~#15'$!3~#240' DO .2 <- !3~#15'$!3~#240' DO .1 <- .5 DO (1010) NEXT DO .5 <- .2 DO ,1SUB#1 <- .3 (30) PLEASE READ OUT ,1
For each number received in the input array, the program first tests
#256 bit to see if the end of file has been reached.
If not, the previous input character is subtracted off to obtain the
current input character. Then the order of the bits is reversed to
find out what character should be sent to the output, and the result
is subtracted from the last character sent. Finally, the difference
is placed in an array and given to a
READ OUT statement.
See? We told you it was simple!