The INTERCAL Programming Language
Revised Reference Manual



Donald R. Woods
and
James M. Lyon

C-INTERCAL revisions:
Louis Howell
and
Eric S. Raymond








Copyright © 1973 by Donald R. Woods
and James M. Lyon
Copyright © 1996 by Eric S. Raymond
Redistribution encouraged under GPL

(This version distributed with C-INTERCAL 0.15)

Introduction

"But I don't want to go among mad people," Alice remarked.

"Oh, you ca'n't help that," said the Cat: "We're all mad here. I'm mad. You're mad."

"How do you know I'm mad?" said Alice. "You must be," said the Cat, "or you wouldn't have come here."

The names you are about to ignore are true. However, the story has been changed significantly. Any resemblance of the programming language portrayed here to other programming languages, living or dead, is purely coincidental.

Origin and Purpose

The INTERCAL programming language was designed the morning of May 26, 1972 by Donald R. Woods and James M. Lyon, at Princeton University. Exactly when in the morning will become apparent in the course of this manual.

Eighteen years later (give or take a few months) Eric S. Raymond perpetrated a UNIX-hosted INTERCAL compiler as a weekend hack. The C-INTERCAL implementation has since been maintained and extended by an international community of technomasochists, including Louis Howell, Steve Swales, Michael Ernst, and Brian Raiter.

(There was evidently an Atari implementation sometime between these two; notes on it got appended to the INTERCAL-72 manual. The culprits have sensibly declined to identify themselves.)

INTERCAL was inspired by one ambition: to have a compiler language which has nothing at all in common with any other major language. By 'major' was meant anything with which the authors were at all familiar, e.g., FORTRAN, BASIC, COBOL, ALGOL, SNOBOL, SPITBOL, FOCAL, SOLVE, TEACH, APL, LISP, and PL/1. For the most part, INTERCAL has remained true to this goal, sharing only the basic elements such as variables, arrays, and the ability to do I/O, and eschewing all conventional operations other than the assignment statement (FORTRAN "=").

Acronym

The full name of the compiler is "Compiler Language With No Pronounceable Acronym", which is, for obvious reasons, abbreviated "INTERCAL".

Acknowledgements

The authors are deeply indebted to Eric M. Van and Daniel J. Warmenhoven, without whose assistance this manual would still have been possible.


Fundamental Concepts

"There's nothing like eating hay when you're faint," the White King remarked to Alice, as he munched away.

"I should think throwing cold water over you would be better," Alice said: "— or some sal-volatile."

"I didn't say there was nothing better," the King replied. "I said there was nothing like it." Which Alice did not venture to deny.

In this section an attempt is made to describe how and why INTERCAL may be used; i.e., what it is like and what it is good for.

Sample Program

Shown below is a relatively simple INTERCAL program which will read in 32-bit unsigned integers, treat them as signed, 2's-complement numbers, and print out their absolute values. The program exits if the absolute value is zero. Note in particular the inversion routine (statements 6 through 14), which could be greatly simplified if the subroutine library (see section 7) were used.

A more detailed analysis of a program is made in section 8 of this manual.


      DO (5) NEXT
  (5) DO FORGET #1
      PLEASE WRITE IN :1
      DO .1 <- '∀":1˜'#32768¢#0'"¢#1'˜#3
      DO (1) NEXT
      DO :1 <- "'∀":1˜'#65535¢#0'"¢#65535'
              ˜'#0¢#65535'"¢"'∀":1˜'#0¢65535'"
              ¢#65535'˜'#0¢#65535'"
      DO :2 <- #1
      PLEASE DO (4) NEXT
  (4) DO FORGET #1
      DO .1 <- "∀':1˜2:2'¢#1"˜#3
      DO :1 <- "'∀":1˜'#65535¢3#0'"¢":2˜'#65535
              ¢#0'"'˜'#0¢#65535'"¢"'∀":1˜'#0
              ¢#65535'"¢":2˜'#0¢#65535'"'˜'#0¢#65535'"
      DO (1) NEXT
      DO :2 <- ":2˜'#0¢#65535'"
              ¢"'":2˜'#65535¢"0'"¢"0'˜'#32767¢#1'"
      DO (4) NEXT
  (2) DO RESUME .1
  (1) PLEASE DO (2) NEXT
      PLEASE FORGET #1
      DO READ OUT :1
      PLEASE DO .1 <- '∀"':1˜:1'˜#1"¢"1'˜#3
      DO (3) NEXT
      PLEASE DO (5) NEXT
  (3) DO (2) NEXT
      PLEASE GIVE UP

Uses for INTERCAL

INTERCAL's main advantage over other programming languages is its strict simplicity. It has few capabilities, and thus there are few restrictions to be kept in mind. Since it is an exceedingly easy language to learn, one might expect it would be a good language for initiating novice programmers. Perhaps surprising, then, is the fact that it would be more likely to initiate a novice into a new line of work. As it turns out, INTERCAL is more useful (which isn't saying much) as a challenge to professional programmers. Those who doubt this need only refer back to the sample program in section 2.1. This 22-statement program took somewhere from 15 to 30 minutes to write, whereas the same objectives can be achieved by single-statement programs in either SNOBOL:


  PLEASE INPUT POS(0) ('-' ! ")
  + (SPAN('0123456789') $ OUTPUT)
  + *NE(OUTPUT) :S(PLEASE)F(END)

or APL;


  [1] →0≠⎕←∣⎕

Admittedly, neither of these is likely to appear more intelligible to anyone unfamiliar with the languages involved, but they took roughly 60 seconds and 15 seconds, respectively, to write. Such is the overwhelming power of INTERCAL!

The other major importance of INTERCAL lies in its seemingly inexhaustible capacity for amazing one's fellow programmers, confounding programming shop managers, winning friends, and influencing people. It is a well-known and oft-demonstrated fact that a person whose work is incomprehensible is held in high esteem. For example, if one were to state that the simplest way to store a value of 65536 in a 32-bit INTERCAL variable is:


  DO :1 <- #0¢#256

any sensible programmer would say that that was absurd. Since this is indeed the simplest method, the programmer would be made to look foolish in front of his boss, who would of course have happened to turn up, as bosses are wont to do. The effect would be no less devastating for the programmer having been correct.


Description

"I quite agree with you," said the Duchess; "and the moral of that is — 'Be what you seem to be' — or, if you'd like it put more simply — 'Never imagine yourself not to be otherwise than what it might appear to others that what you were or might have been was not otherwise than what you had been would have appeared to them to be otherwise.'"
"I think I should understand that better," Alice said very politely, "if I had it written down; but I ca'n't quite follow it as you say it."

"That's nothing to what I could say if I chose," the Duchess replied, in a pleased tone.

The examples of INTERCAL programming which have appeared in the preceding sections of this manual have probably seemed highly esoteric to the reader unfamiliar with the language. With the aim of making them more so, we present here a description of INTERCAL.

Variables

INTERCAL allows only 2 different types of variables, the 16-bit integer and the 32-bit integer. These are represented by a spot (.) or a two-spot (:), respectively, followed by any number between 1 and 65535, inclusive. These variables may contain only non-negative numbers; thus they have the respective ranges of values: 0 to 65535 and 0 to 4294967295. Note: .123 and :123 are two distinct variables. On the other hand, .1 and .0001 are identical. Furthermore, the latter may NOT be written as 1E-3.

Constants

Constants are 16-bit values only and may range from 0 to 65535. They are prefixed by a mesh (#). Caution! Under no circumstances confuse the mesh with the interleave operator, except under confusing circumstances!

Arrays

Arrays are represented by a tail (,) for 16-bit values, or a hybrid (;) for 32-bit values, followed by a number between 1 and 65535, inclusive. The number is suffixed by the word SUB, followed by the subscripts, separated optionally by spaces. Subscripts may be any expressions, including those involving subscripted variables. This occasionally leads to ambiguous constructions, which are resolved as discussed in section 3.4.3. Definition of array dimensions will be discussed later in greater detail, since discussing it in less detail would be difficult. As before, ,123 and ;123 are distinct. In summary, .123, :123, #123, ,123, and :123 are all distinct.

Operators

INTERCAL recognizes 5 operators — 2 binary and 3 unary. Please be kind to our operators; they may not be very intelligent, but they're all we've got. In a sense, all 5 operators are binary, as they are all bit-oriented, but it is not our purpose here to quibble about bits of trivia.

Binary Operators

The binary operators are interleave (also called mingle) and select, which are represented by a change (¢) and a sqiggle [sic] (˜), respectively. (In C-INTERCAL's ASCII environment, EBCDIC ¢ is replaced by a big money ($).)

The interleave operator takes two 16-bit values and produces a 32-bit result by alternating the bits of the operands. Thus, #65535¢#0 has the 32-bit binary form 101010…10 or 2863311530 decimal, while #0¢#65535 = 0101…01 binary = 1431655765 decimal, and #255¢#255 is equivalent to #65535.

The select operator takes from the first operand whichever bits correspond to 1's in the second operand, and packs those bits to the right in the result. Both operands are automatically padded on the left with zeros to 32 bits before the selection takes place, so the variable types are unrestricted. If more than 16 bits are selected, the result is a 32-bit value, otherwise it is a 16-bit value. For example, #179˜#201 (binary value 10110011˜11001001) selects from the first argument the 8th, 7th, 4th, and 1st from last bits, namely, 1001, which = 9. But #201˜#179 selects from binary 11001001 the 8th, 6th, 5th, 2nd and 1st from last bits, giving 10001 = 17. #179˜#179 has the value 31, while #201˜#201 has the value 15.

Return type of SELECT

INTERCAL-72 defined the return type of a SELECT operation to depend on the number of bits SELECTed. The C-INTERCAL compiler takes the easier route of defining the return type to be that of the right operand, independent of its actual value. This form has the advantage that all types can be determined at compile time. Putting in run time [sic] type checking would add significant overhead and complication, to effect a very minor change in language semantics.

The only time this distinction makes any difference is when a unary operator is applied to the SELECT result. This happens extremely rarely in practice, the only known instance being the 32-bit greater-than test in the standard library, where an XOR operator is applied to the result of SELECTing a number against itself. The INTERCAL-72 authors first SELECT the result against #65535¢#65535 to insure that XOR sees a 32-bit value. With the current compiler this step is unnecessary, but harmless.

The cautious programmer should write code that does not depend on the compiler version being used. We therefore suggest the following guideline for determining the SELECT return type:

A SELECT operation with a 16-bit right operand returns a 16-bit value. THe return type of a SELECT operation with a 32-bit right operand is undefined, but is guaranteed to be an acceptable input to a MINGLE operation so long as 16 or fewer bits are actually selected. Correct code should not depend on whether the return type is 16 or 32 bits.

Perhaps a simpler way of understanding the operation of the select operator would be to examinme the logic diagram on the following page (Figure 1), which performs the select operation upon two 8-bit values, A and B. The gates used are Warmenhovian logic gates, which means the outputs have four possible values: low, high, undefined (value of an uninitialized flip-flop), and oscillating (output of a NOR gate with one input low and the other input connected to the output). These values are represented symbolically by '0' '1', '?', and '∅'. Note in particular that, while NOT-0 is 1 and NOT-1 is 0 as in two-valued logic, NOT-? is ? and NOT-∅ is ∅. The functions of the various gates are listed in Table 1.