"There's glory for you!"
"I don't know what you mean by 'glory,'" Alice said.
Humpty Dumpty smiled contemptuously. "Of course you don't--till I tell you. I meant 'there's a nice knock-down argument for you!'"
"But 'glory' doesn't mean 'a nice knock-down argument.'" Alice objected.
"When I use a word," Humpty Dumpty said, in a rather scornful tone, "it means just what I choose it to mean--neither more nor less."
In this section is described the format of INTERCAL statements.
Statements may be entered in "free format". That is, more than one statement may occur on a single card (or line), and a statement may begin on one card (line) and end on a later one. Note that if this is done, all intervening cards and portions thereof must be part of the same statement. That this restriction is necessary is immediately apparent from the following example of what might occur if statements could be interlaced.
DO .1 <- ".1$'&:51~"#?1$!12~;&75SUB"?'V.1~ DO .2 <- '"!1$"&';?79SUB",&7SUB:173"'~!?9$ .2'$,&1SUB:5~#33578"'"'"~'#65535$"?'V#&85'"' #8196'"'~.1"$.2'~'#&5$"'#1279$#4351'~#65535"'
The above statements are obviously meaningless. (For that matter, so are the statements
DO .1 <- ".1$'&:51~"#?1$!12~;&75SUB"?'V.1~ .2'$,&1SUB:5~#33578"'"'"~'#65535$"?'V#&85'"' DO .2 <- '"!1$"&';?79SUB",&7SUB:173"'~!?9$ #8196'"'~.1"$.2'~'#&5$"'#1279$#4351'~#65535"'
but this is not of interest here.)
Spaces may be used freely to enhance program legibility (or at least reduce program illegibility), with the restriction that no word of a statement identifier (see section 4.3) may contain any spaces.
A statement may begin with a logical line label enclosed in
wax-wane pairs (
()). A statement may not have more than
one label, although it is possible to omit the label entirely. A line
label is any integer from
must be unique within each program. The user is cautioned, however,
that many line labels between
are used in the INTERCAL System Library functions.
After the line label (if any), must follow one of the following
PLEASE DO. These may be used interchangeably to improve
the aesthetics of the program. The identifier is then followed by
either, neither, or both of the following optional parameters
(qualifiers): (1) either of the character strings
N'T, which causes the statement to be automatically
abstained from (see section 4.4.9) when execution
begins, and (2) a number between
preceded by a double-oh-seven (
%), which causes the
statement to have only the specified percent chance of being executed
each time it is encountered in the course of execution.
Following the qualifiers (or, if none are used, the identifier) must occur one of the 14 valid operations. (Exception: see section 4.5.) These are described individually in the following sections.
The INTERCAL equivalent of the half-mesh (
=) in FORTRAN,
BASIC, PL/I, and others, is represented by an angle
<) followed by a worm (
combination is read "gets". 32-bit variables may be assigned 16-bit
values, which are padded on the left with 16 zero bits. 16-bit
variables may be assigned 32-bit values only if the value is less than
65535. Thus, to invert the least significant bit of the first element
of 16-bit 2-dimensional array number 1, one could write:
,1SUB#1#1 <- '?",1SUB#1#1"$#1'~'#0$#65535'
Similarly to SNOBOL and SPITBOL, INTERCAL uses the angle-worm to define the dimensions of arrays. An example will probably best describe the format. To define 32-bit array number 7 as 3-dimensional, the first dimension being seven, the second being the current value of 16-bit variable number seven, and the third being the current value of the seventh element of 16-bit array number seven (which is one-dimensional) mingled with the last three bits of 32-bit variable number seven, one would write (just before they came to take him away):
;7 <- #7 BY .7 BY ",7SUB#7"$':7~#7'
This is, of course, different from the statement:
;7 <- #7 BY .7 BY ,7SUB"#7$':7~#7'"
INTERCAL also permits the redefining of array dimensioning, which is
done the same way as is the initial dimensioning. All values of items
in an array are lost upon redimensioning, unless they have been
STASHed (see section 4.4.5), in which
case restoring them also restores the old dimensions.
NEXT statement is used both for subroutine calls and
for unconditional transfers. This statement takes the form:
DO (label) NEXT
(or, of course,
PLEASE DO (label) NEXT
etc.), where (label) represents any logical line label
which appears in the program. The effect of such a statement is to
transfer control to the statement specified, and to store in a push
down list (which is initially empty) the location from which the
transfer takes place. Items may be removed from this list and may be
discarded or used to return to the statement immediately following the
NEXT statement. These operations are described in section 4.4.3 and section 4.4.4
respectively. The programmer is generally advised to discard any
stack entries which he does not intend to utilize, since the stack has
a maximum depth of 79 entries. A program's attempting to initiate an
80th level of
NEXTing will result in the fatal error
message, PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON.
PLEASE FORGET exp, where
exp represents any expression (except colloquial and facial
expressions), causes the expression to be evaluated, and the specified
number of entries to be removed from the
and discarded. An attempt to
FORGET more levels of
NEXTing than are currently stacked will cause the stack
to be emptied, and no error condition is indicated. This is because
the condition is not considered to be an error. As described in
section 4.4.2, it is good programming practice to
DO FORGET #1 after using a
statement as an unconditional transfer, so that the stack does not get
cluttered up with unused entries:
DO (123) NEXT . . (123) DO FORGET #1
PLEASE RESUME exp has the same
FORGET, except that program control is returned
to the statement immediately following the
which stored in the stack the last entry to be removed. Note that a
rough equivalent of the FORTRAN computed
GO TO and BASIC
GO TO is performed by a
sequence of the form:
DO (1) NEXT . . (1) DO (2) NEXT PLEASE FORGET #1 . . (2) DO RESUME .1
FORGET statement, an attempt to
RESUME more levels of
NEXTing than has been
stacked will cause program termination. See also
Since subroutines are not explicitly implemented in INTERCAL, the
RESUME statements must be used to
execute common routines. However, as these routines might use the
same variables as the main program, it is necessary for them to save
the values of any variables whose values they alter, and later restore
them. This process is simplified by the
which has the form
DO STASH list, where
list represents a string of one or more variable or array
names, separated by intersections (
PLEASE STASH .123+:123+,123
stashes the values of two variables and one entire array. The values
are left intact, and copies thereof are saved for later retrieval by
(what else?) the
RETRIEVE statement (see
section 4.4.6). It is not possible to
STASH single array items.
PLEASE RETRIEVE list restores the previously
STASHed values of the variables and arrays named in the
list. If a value has been stashed more than once, the most
STASHed values are
RETRIEVEd, and a
RETRIEVE will restore the second most recent
STASHed. Attempting to
value which has not been
STASHed will result in the error
message, THROW STICK BEFORE RETRIEVING.
DO IGNORE list causes all
subsequent statements to have no effect upon variables and/or arrays
named in list. Thus, for example, after the sequence
DO .1 <- #1 PLEASE IGNORE .1 DO .1 <- #0
16-bit variable number 1 would have the value 1, not 0. Inputting and
retrieving (see section 4.4.12 and
section 4.4.6) into an ignored variable also has no
effect on the variable, and the values that would have been input or
retrieved are discarded. The condition is annulled via the
REMEMBER statement (see section
4.4.8). Note that, when a variable is being
its value, though immutable, is still available for use in expressions
and the like.
PLEASE REMEMBER list terminates the effect of
IGNORE statement for all variables and/or arrays
named in the list. It does not matter if a variable has
IGNOREd more than once, nor is it an error if the
variable has not been
IGNOREd at all.
INTERCAL contains no simple equivalent to an
GO TO, making it difficult to combine similar
sections of code into a single routine which occasionally skips around
certain statements. The
IGNORE statement (see
section 4.4.7) is helpful in some cases, but a more
viable method is often required. In keeping with the goal of INTERCAL
having nothing in common with any other language, this is made
possible via the
This statement takes on one of two forms. It may not take on both at
any one time.
DO ABSTAIN FROM (label) causes
the statement whose logical line label is (label) to be
PLEASE ABSTAIN FROM gerund
list causes all statements of the specified type(s) to be
abstained from, as in
PLEASE ABSTAIN FROM STASHING PLEASE ABSTAIN FROM IGNORING + FORGETTING PLEASE ABSTAIN FROM NEXTING PLEASE ABSTAIN FROM CALCULATING
Statements may also be automatically abstained from at the start of
execution via the
N'T parameter (see
If, in the course of execution, a statement is encountered which is being abstained from, it is ignored and control passes to the next statement in the program (unless it, too, is being abstained from).
DO ABSTAIN FROM ABSTAINING is perfectly
valid, as is
DO ABSTAIN FROM REINSTATING (although this
latter is not usually recommended). However, the statement
ABSTAIN FROM GIVING UP is not accepted, even though
GIVE UP is.
REINSTATE statement, like
as an argument either a line label or a gerund list. No other form of
argument is permitted. For example, the following is an invalid
Given: x not equal to 0, y not equal to 0, Prove: x + y = 0.
Since x does not equal 0, then x + 1 does not equal 1, x + a does not equal a, x + y does not equal y.
But what is y? y is anything but 0.
Thus x + y is not equal to anything but 0.
Since x + y cannot equal anything but 0, x + y = 0.
REINSTATEment nullifies the effects of an abstention.
Either form of
REINSTATEment can be used to "free" a
statement, regardless of whether the statement was abstained from by
gerund list, line label, or
REINSTATE REINSTATING is not necessarily an irrelevant
statement, since it might free a
DON'T REINSTATE command
REINSTATE the line label of which was abstained
DO REINSTATE GIVING UP is invalid, and
GIVE UP statement
by line label will have no effect. Note that this insures that
DON'T GIVE UP will always be a "do-nothing" statement.
PLEASE GIVE UP is used to exit from a program. It has
the effect of a
PLEASE RESUME #80.
UP, as noted in section 4.4.10, is
effectively a null statement.
Input is accomplished with the statement
DO WRITE IN
list, where list represents a string of
variables and/or elements of arrays, separated by intersections.
Numbers are represented on cards, each number on a separate card, by
spelling out each digit (in English) and separating the digits with
one or more spaces. Thus the range of (32-bit) input values
permissible extends from ZERO through FOUR TWO NINE
FOUR NINE SIX SEVEN TWO NINE FIVE. A zero (0) may be spelled
as either ZERO or OH, and, for the
convenience of aviators, C-INTERCAL accepts the spelling
NINER for NINE. In the service of
internationalization, C-INTERCAL also accepts input digits in
Sanskrit, Basque, Tagalog, Classical Nahuatl, Georgian, Kwakiutl, and
Attempting to write in a value greater than or equal to SIX FIVE FIVE THREE SIX for a 16-bit variable will result in the error message, DON'T BYTE OFF MORE THAN YOU CAN CHEW.
The programmer desiring to handle input on a character basis should consider using another language. Failing that, refer to section 5.
Values may be output to the printer (or screen), one value per line,
via the statement
DO READ OUT list, where the
list contains variables, array elements, and/or constants.
Output is in the form of "extended" Roman numerals (also called
"butchered" Roman numerals), with an overline indicating the value
below is "times 1000", and lower-case letters indicating "times
1000000". Zero is indicated by an overline with no character
underneath. Thus, the range of (32-bit) output values possible is from
#3999would read out as
#4000would read out as
READ OUTstatement can also be used with arrays to produce other kinds of output; see section 5.
The earliest known description of the
COME FROM statement
in the computing literature is in R. L. Clark, "A linguistic
contribution to GOTO-less programming," Commun. ACM 27 (1984),
pp. 349-350, part of the famous April Fools issue of CACM. The
subsequent rush by language designers to include the statement in
their languages was underwhelming, one might even say nonexistent. It
was therefore decided that
COME FROM would be an
appropriate addition to C-INTERCAL.
There are two useful ways to visualize the action of the
FROM statement. The simpler is to see that it acts like a
GOTO when the program is traced backwards in time. More
precisely, the statements
(1) DO <any statement> . . . (2) DO COME FROM (1)
should be thought of as being equivalent to
(1) DO <any statement> (2) DO GOTO (3) . . . (3) DO NOTHING
if INTERCAL actually had a
GOTO statement at all, which
of course it doesn't.
What this boils down to is that the statement
DO COME FROM
(label), anywhere in the program, places a kind of
invisible trap door immediately after statement (label).
Execution or abstention of that statement is immediately followed by
an unconditional jump to the
COME FROM, unless the
(label)ed statement is an executed
which case the jump occurs if the program attempts to
RESUME back to that
NEXT statement. It is
an error for more than one
COME FROM to refer to the same
Modification of the target statement by
ABSTAIN or by the
% qualifier affects only that statement, not the
subsequent jump. Such modifications to the
itself, however, do affect the jump. Encountering the
FROM statement itself, rather than its target, has no effect.
Unrecognizable statements, as noted in section 9, are flagged with a splat (*) during compilation, and are not considered fatal errors unless they are encountered during execution, at which time the statement (as input at compilation time) is printed and execution is terminated. This allows for an interesting (and, by necessity, unique) means of including comments in an INTERCAL listing. For example, the statement:
* PLEASE NOTE THAT THIS LINE HAS NO EFFECT
will be ignored during execution due to the inclusion of the
NOT qualifier. User-supplied error messages are also
easy to implement:
* DO SOMETHING ABOUT OVERFLOW IN ;3
as are certain simple conditional errors:
* (123) DON'T YOU REALIZE THIS STATEMENT SHOULD ONLY BE ENCOUNTERED ONCE? PLEASE REINSTATE (123)
This pair of statements will cause an error exit the second time they are encountered. Caution! The appearance of a statement identifier in an intended comment will be taken as the beginning of a new statement. Thus, the first example on the preceding page could not have been:
* PLEASE NOTE THAT THIS LINE DOES NOTHING
The third example, however, is valid, despite the appearance of two cases of D-space-O, since INTERCAL does not ignore extraneous spaces in statement identifiers.
(Note that the C-INTERCAL compiler does not produce a program listing during compilation, this being a rather less necessary feature of a compiler when text files are used in place of punch cards. Thus, the comments regarding splat-flagged lines do not apply to C-INTERCAL.)
* The original INTERCAL-72 manual claimed that
should render as MMMIM, but the C-INTERCAL developers
have been unable to find an algorithm that does this and is consistent
with the rest of the rules.