"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."


4. Statements

In this section is described the format of INTERCAL statements.

4.1 General Format

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.

4.2 Labels

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 1 to 65535, which must be unique within each program. The user is cautioned, however, that many line labels between 1000 and 1999 are used in the INTERCAL System Library functions.

4.3 Identifiers and Qualifiers

After the line label (if any), must follow one of the following statement identifiers: DO, PLEASE, or 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 NOT or N'T, which causes the statement to be automatically abstained from (see section 4.4.9) when execution begins, and (2) a number between 0 and 100, 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.

4.4 Statements

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.

4.4.1 Calculate

The INTERCAL equivalent of the half-mesh (=) in FORTRAN, BASIC, PL/I, and others, is represented by an angle (<) followed by a worm (-). This 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.

4.4.2 NEXT

The 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.

4.4.3 FORGET

The statement 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 NEXTing stack 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 execute a DO FORGET #1 after using a NEXT statement as an unconditional transfer, so that the stack does not get cluttered up with unused entries:

        DO (123) NEXT
        .
        .
  (123) DO FORGET #1

4.4.4 RESUME

The statement PLEASE RESUME exp has the same effect as FORGET, except that program control is returned to the statement immediately following the NEXT statement which stored in the stack the last entry to be removed. Note that a rough equivalent of the FORTRAN computed GO TO and BASIC ON exp GO TO is performed by a sequence of the form:

        DO (1) NEXT
        .
        .
    (1) DO (2) NEXT
        PLEASE FORGET #1
        .
        .
    (2) DO RESUME .1

Unlike the FORGET statement, an attempt to RESUME more levels of NEXTing than has been stacked will cause program termination. See also section 4.4.11.

4.4.5 STASH

Since subroutines are not explicitly implemented in INTERCAL, the NEXT and 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 STASH statement, which has the form DO STASH list, where list represents a string of one or more variable or array names, separated by intersections (+). Thus

	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.

4.4.6 RETRIEVE

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 recently STASHed values are RETRIEVEd, and a second RETRIEVE will restore the second most recent values STASHed. Attempting to RETRIEVE a value which has not been STASHed will result in the error message, THROW STICK BEFORE RETRIEVING.

4.4.7 IGNORE

The statement 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 IGNOREd, its value, though immutable, is still available for use in expressions and the like.

4.4.8 REMEMBER

PLEASE REMEMBER list terminates the effect of the IGNORE statement for all variables and/or arrays named in the list. It does not matter if a variable has been IGNOREd more than once, nor is it an error if the variable has not been IGNOREd at all.

4.4.9 ABSTAIN

INTERCAL contains no simple equivalent to an IF statement or computed 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 ABSTAIN statement.

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 abstained from. 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 NOT or N'T parameter (see section 4.3).

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).

The statement DO ABSTAIN FROM ABSTAINING is perfectly valid, as is DO ABSTAIN FROM REINSTATING (although this latter is not usually recommended). However, the statement DO ABSTAIN FROM GIVING UP is not accepted, even though DON'T GIVE UP is.

4.4.10 REINSTATE

The REINSTATE statement, like ABSTAIN, takes 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 argument:

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.

Q.E.D.

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 NOT. Thus, PLEASE REINSTATE REINSTATING is not necessarily an irrelevant statement, since it might free a DON'T REINSTATE command or a REINSTATE the line label of which was abstained from. However, DO REINSTATE GIVING UP is invalid, and attempting to REINSTATE a 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.

4.4.11 GIVE UP

PLEASE GIVE UP is used to exit from a program. It has the effect of a PLEASE RESUME #80. DON'T GIVE UP, as noted in section 4.4.10, is effectively a null statement.

4.4.12 Input

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 Volapuk.

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.

4.4.13 Output

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

_
 
through
__      ____________
ivccxcivCMLXVIICCXCV
Note: For values whose residues modulo 1000000 are less than 4000,
 
M
is used to represent 1000; for values whose residues are 4000 or greater,
_
I
is used. Thus #3999 would read out as
         
MMMCMXCIX
*
while #4000 would read out as
__
IV
Similar rules apply to the representation of values of the order of 1000000 and 1000000000. The READ OUT statement can also be used with arrays to produce other kinds of output; see section 5.

4.4.14 COME FROM

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 COME 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 NEXT, in 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 (label).

Modification of the target statement by ABSTAIN or by the % qualifier affects only that statement, not the subsequent jump. Such modifications to the COME FROM itself, however, do affect the jump. Encountering the COME FROM statement itself, rather than its target, has no effect.

4.5 Comments

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 #3999 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.


[Next]
[Previous]
[Contents]