INTERCAL

Appeared in:
1972
Influenced:
Paradigm:
Typing discipline:
Versions and implementations (Collapse all | Expand all):
Programming language

INTERCAL (full name is Compiler Language With No Pronounceable Acronym, so short name is rather random) is one of the oldest esoteric programming languages.

It was developed in 1972 as a parody on other languages that existed at that time; modern esoteric languages beat it in weirdness, but some aspects of it, like character output, are beyond compare. Its reference manual is a work of art on itself (unlike modern languages, which concentrate on meaning of commands, not on literal description), with special names for nearly every common thing.

One of the features INTERCAL is famous for is its PLEASE modifier: it serves no other purpose than to make programmer polite, but not too polite.

Elements of syntax:

Inline comments PLEASE NOTE: ... (skipped due to NOT)

Examples:

Hello, World!:

Example for versions J-INTERCAL 0.11, J-INTERCAL 0.12, c-intercal 28.0

INTERCAL is one of the languages in which even writing “Hello, World!” is a torture. The trick is, C-INTERCAL’s command READ OUT implements character output on Turing Tape method. To use it, the output argument must be an array, which we have stored in ,1 (, means that the variable is an array of 16-bit integers). The values of the array produce output one by one, from left to right. To figure out what character to output based on i-th element of the array, the compiler performs the following actions:

  1. Bit-reverse ASCII-code of previous printed character (assuming it’s 8-bit) to get rev(i-1). When outputting first element of the array, this is assumed to be 0.
  2. Get the i-th element of the array array(i).
  3. Subtract array(i) from rev(i-1) to get rev(i).
  4. Bit-reverse rev(i) to get ASCII-code of the character to be printed i-th.

Another thing to note is the usage of PLEASE modifier. This program must contain 4 or 5 PLEASE, the lines where they are located don’t really matter. 3 or less PLEASE result in “ICL079I PROGRAMMER IS INSUFFICIENTLY POLITE” error, while 6 or more yield “ICL099I PROGRAMMER IS OVERLY POLITE” error.

Other commands and expressions are trivial (at least compared to previous ones): # is a constant prefix, <- is assignment, SUB is subscript of an array. The first line of the example states that ,1 is an array of 16-bit integers, and it will have 13 elements.

DO ,1 <- #13
PLEASE DO ,1 SUB #1 <- #238
DO ,1 SUB #2 <- #108
DO ,1 SUB #3 <- #112
DO ,1 SUB #4 <- #0
DO ,1 SUB #5 <- #64
DO ,1 SUB #6 <- #194
PLEASE DO ,1 SUB #7 <- #48
DO ,1 SUB #8 <- #26
DO ,1 SUB #9 <- #244
PLEASE DO ,1 SUB #10 <- #168
DO ,1 SUB #11 <- #24
DO ,1 SUB #12 <- #16
DO ,1 SUB #13 <- #162
PLEASE READ OUT ,1
PLEASE GIVE UP

Fibonacci numbers:

Example for versions J-INTERCAL 0.11, J-INTERCAL 0.12, c-intercal 28.0

This example uses iterative definition of Fibonacci numbers. Variables .10 and .11 store previous and current calculated numbers, and .9 stores the number of iterations left.

Loop body is quite simple: print current number .11, copy .10 and .11 to .1 and .2, add them ((1009) NEXT calls addition from standard library and puts sum to .3) and update the values. The trickiest part of the program is the code that implements looping behavior. Here is what it does.

(3) NEXT and (4) NEXT move execution to label (4). At this line the loop counter .9 is updated by subtracting 1 from it (call of (1010)). After this, .1 is calculated in a rather complicated way that makes it 1 if .9 is non-zero, and 0 otherwise. After this, .1 is incremented to be 1 if the loop has to stop (loop counter is zero) and 2 otherwise. Finally, RESUME .1 is performed to return to one of the NEXTs applied. If .1 is 2, the program returns two NEXTs back, and continues with DO (1) NEXT which brings it to the start of the loop again. However, if .1 is 1, the program returns one NEXT back, continues with PLEASE GIVE UP and halts.

Note that numbers are printed in Roman notation (this language lets not a single thing be easy!), one number per two lines (line which is empty in this example is for modifiers), so the output looks like this:

I

I

II

III

V

VIII

XIII

XXI

XXXIV

LV

LXXXIX

CXLIV

CCXXXIII

CCCLXXVII

DCX

CMLXXXVII

    DO .9 <- #16
    DO .10 <- #0
    DO .11 <- #1

(1) PLEASE READ OUT .11
    DO .1 <- .10
    DO .2 <- .11
    PLEASE (1009) NEXT
    DO .10 <- .11
    DO .11 <- .3

    DO (3) NEXT
    DO (1) NEXT

(3) DO (4) NEXT
    PLEASE GIVE UP

(4) DO .1 <- .9
    DO .2 <- #1
    PLEASE (1010) NEXT
    DO .9 <- .3
    DO .1 <- '.9~.9'~#1
    PLEASE (1020) NEXT
    DO RESUME .1

Factorial:

Example for versions J-INTERCAL 0.11, J-INTERCAL 0.12, c-intercal 28.0

This example uses iterative factorial definition. The looping part is similar to Fibonacci example, the body differs, but only a little bit. Note usage of : prefix for variables instead of . — the former means 32-bit variables, and the latter — 16-bit ones. The output looks as follows (numbers go in pairs, n and n!, and each number takes two lines to be written):

_                                                         


I

I

I

II

II

III

VI 

IV 

XXIV

V   

CXX 

VI  

DCCXX

VII  
_    
VXL  

VIII 
__     
XLCCCXX

IX     
_____          
CCCLXMMDCCCLXXX

X              
___________    
MMMDCXXVIIIDCCC

XI             
     _____     
xxxixCMXVIDCCC 

XII            

cdlxxixMDC     

XIII           
      ___      
mcmxxxMMLMMMDIV

XIV
          _____
mcclxxviiiCMXLVCCLXXX

XV
    ____
mmivCCCXXVI

XVI
    _______
mmivCLXXXIXCLXXXIV

C-INTERCAL uses Roman notation, in which a bar over a numeral multiplies its value by 1000, and writing a letter in lowercase multiplies its value by 1000000.

    DO .9 <- #17
    DO :10 <- #0
    DO :11 <- #1

    DO :2 <- :10

(1) PLEASE READ OUT :10
    PLEASE READ OUT :11

    DO :1 <- #1
    PLEASE (1509) NEXT
    DO :10 <- :3
    DO :2 <- :10
    DO :1 <- :11
    PLEASE (1549) NEXT
    DO :11 <- :3

    DO (3) NEXT
    DO (1) NEXT

(3) DO (4) NEXT
    PLEASE GIVE UP

(4) DO .1 <- .9
    DO .2 <- #1
    PLEASE (1010) NEXT
    DO .9 <- .3
    DO .1 <- '.9~.9'~#1
    PLEASE (1020) NEXT
    DO RESUME .1

Hello, World!:

Example for versions CLC-INTERCAL 1.-94.-2

CLC-INTERCAL Baudot-based text I/O mechanism differs from C-INTERCAL’s, but is not much more convenient. Baudot is a 5-bit character encoding, in which each character consists of two codes — shift state and the actual character code. Shift state can be 1..4, and switching between shift states takes special codes 31 (switch from 1|2 to 2 or from 3|4 to 1) and 27 (switch from 1|2 to 3 or from 3|4 to 4). Thus, an array which has to be printed is interpreted as a sequence of codes, each of them being either switch code or print-character code. The array is usually longer than the message, since switch codes are added.

In this example, the message starts with H, which corresponds to Baudot code “1 0x14” (shift state = 1, code = 20). Initially shift state is set to 1, no need to change it, and so the first element of the array is print-character code 20. Next character is e, Baudot “2 0x01”, we have to switch to state 2 (code 31) and print the character (code 1). Next is l, Baudot “2 0x13”, no shift state switching, only print character (code 19), etc.

Note that CLC-INTERCAL doesn’t really care about programmer’s politeness; the example contains much less PLEASE than C-INTERCAL would have required.

DO ,1 <- #18

DO ,1 SUB #1 <- #20
DO ,1 SUB #2 <- #31
DO ,1 SUB #3 <- #1
DO ,1 SUB #4 <- #19
DO ,1 SUB #5 <- #19
DO ,1 SUB #6 <- #24
DO ,1 SUB #7 <- #27
DO ,1 SUB #8 <- #12
DO ,1 SUB #9 <- #4
DO ,1 SUB #10 <- #31
DO ,1 SUB #11 <- #18
DO ,1 SUB #12 <- #31
DO ,1 SUB #13 <- #24
DO ,1 SUB #14 <- #10
DO ,1 SUB #15 <- #19
DO ,1 SUB #16 <- #9
DO ,1 SUB #17 <- #27
DO ,1 SUB #18 <- #13

PLEASE READ OUT ,1
PLEASE GIVE UP