C-INTERCAL

Implementation of programming language INTERCAL

C-INTERCAL is a maintained implementation of INTERCAL. It is written in C and licensed under GNU GPL v2.

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