(Originally posted on a gemlog on October 25, 2023; reformatted for inclusion
here)

How to do nothing in INTERCAL

The other day I posted this on the fediverse:

    This program executes correctly as a CLC-INTERCAL program (it doesn't
    actually do anything, but exits with success).

    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU DO
    GIVE UP ON YOUR GRATUITOUS VIOLENCE
    ACT TO MAKE THE WORLD A BETTER PLACE

(https://polyglot.city/@Uilebheist/111278586725038066)

It's quite possible that people not familiar with INTERCAL might be
wondering how that works (and possibly why it doesn't work with C-INTERCAL
if they tried with that compiler).  So here's a simple explanation.

A statement in INTERCAL starts with DO, PLEASE or PLEASE DO and
ends where the next statement starts (or at the end of the program).
So for C-INTERCAL and other "traditional" compilers, the program has
two statements:

    PLEASE DO NOT FEED HATRED RESPECT YOUR FELLOW HUMANS THEY MATTER AS MUCH AS YOU
    DO GIVE UP ON YOUR GRATUITOUS VIOLENCE ACT TO MAKE THE WORLD A BETTER PLACE

The compiler will not give an error if it cannot understand a statement,
instead running the program will produce the statement itself as error
message if it tries to execute it.

Moreover, if a statement is negated (DO NOT, PLEASE NOT, PLEASE DO NOT,
or else DON'T instead of DO NOT) it is not executed (this is a slight
simplification but it'll do for this program).  So the first statement
is never executed but the second one is.

For CLC-INTERCAL there is an additional rule, that a statement ends where
it stops making sense.  This is necessary because the compiler can change
and make a valid statement shorter than it used to be.  Since "DO GIVE
UP" is a valid statement, asking to end program execution, CLC-INTERCAL
sees the program as:

    PLEASE DO NOT FEED HATRED RESPECT YOUR FELLOW HUMANS THEY MATTER AS MUCH AS YOU
    DO GIVE UP
    ON YOUR GRATUITOUS VIOLENCE ACT TO MAKE THE WORLD A BETTER PLACE

As before, the first statement is skipped, and the second one executed.
Since it means "end the program with success", the third one is not
reached and so the program does what promised, "nothing but exits
with success".  If the program above is saved as "do-not-feed-hatred.i"
one could have the following terminal session:

    $ cat do-not-feed-hatred.i 
    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU DO
    GIVE UP ON YOUR GRATUITOUS VIOLENCE
    ACT TO MAKE THE WORLD A BETTER PLACE
    $ sick do-not-feed-hatred.i 
    $ ./do-not-feed-hatred.io 
    $

Note that there is no error message.

Now looking at C-INTERCAL the situation is different:

    $ ick do-not-feed-hatred.i 
    $ ./do-not-feed-hatred 
    ICL000I THEY MATTER AS MUCH AS YOU DO
	    GIVE UP ON YOUR GRATUITOUS VIOLENCE
	    ACT TO MAKE THE WORLD A BETTER PLACE

	    ON THE WAY TO 7
	    CORRECT SOURCE AND RESUBNIT
    $

There appear to be two differences here.  One is that the line containing
"DO" is interpreted as starting a new statement not where the "DO"
appears, but at the start of that same line.  More on this point below.
And two, as explained above the statement extends to the end of the
program, so it's not a simple "DO GIVE UP".

If however we remove everything after the GIVE UP it now all works
with C-INTERCAL:

    $ cat do-not-feed-hatred.i 
    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU DO
    GIVE UP
    $ ick do-not-feed-hatred.i 
    $ ./do-not-feed-hatred 
    $

So in fact the "DO GIVE UP" is recognised correctly, it's just the
error message from "ick" that it's not quite what one would expect.
This is probably because they count in lines, and CLC-INTERCAL counts
in characters.

As mentioned before, a negated statement is not executed.  So what if we
negate the "DO GIVE UP"?  We'll have to change the sentence, otherwise
it would be quite wrong, so we'll have this program:

    $ cat do-not-feed-hatred.i 
    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU!
    DO NOT GIVE UP ON HELPING PEOPLE.
    $ sick do-not-feed-hatred.i 
    $ ./do-not-feed-hatred.io 
    *000 ON HELPING PEOPLE.
    $

Now we see that CLC-INTERCAL still recognises "DO NOT GIVE UP" as
a statement, but this time it's negated so it doesn't do anything.
Execution proceeds to "ON HELPING PEOPLE." which is not understood and
therefore produces as error message.

As expected, C-INTERCAL considers the whole of the last line as a single
statement, so the error is quite different: the program reaches the end
without being told to either exit with success or encountering an error,
and that's not acceptable:

    $ cat do-not-feed-hatred.i 
    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU!
    DO NOT GIVE UP ON HELPING PEOPLE.
    $ ick do-not-feed-hatred.i 
    $ ./do-not-feed-hatred
    ICL129I PROGRAM HAS GOTTEN LOST
	    ON THE WAY TO WHO KNOWS WHERE
	    CORRECT SOURCE AND RESUBNIT
    $

CLC-INTERCAL would also produce an error on reaching the end of the
program:

    $ cat do-not-feed-hatred.i
    PLEASE DO NOT FEED HATRED
    RESPECT YOUR FELLOW HUMANS
    THEY MATTER AS MUCH AS YOU!
    DO NOT GIVE UP
    $ sick do-not-feed-hatred.i
    $ ./do-not-feed-hatred.io 
    *633 Falling off the edge of the program
    $

Different error code and error message, but same thing really.

Well, this will be all.  Having read so far you now know how to write
a valid INTERCAL program which doesn't do anything, but also does not
produce an error.  Or how to produce an error message, if that's what
you want to do.

Another day we'll explain how do actually do something.  We are building
up to understanding a very simple program like this one:

    PLEASE NOTE: This is a *real* "HELLO, WORLD" program --
    not one of those useless things which print the string "HELLO, WORLD".

    This program writes a string in from standard input, and produces an
    error if the string was not "HELLO, WORLD". If it was, it succeds silently.

    This program requires CLC-INTERCAL

    PLEASE ;1 <- #12
(1) PLEASE WRITE IN ;1
    PLEASE GIVE UP

    PLEASE PLEASE PLEASE (PRETTY PLEASE)
    DO NOT ASK ME TO SEE THE REST OF THIS PROGRAM

    DO COME FROM '".1/'"'¥#29¢"';1SUB#1'~#65535"'~'#0¢#65535'"~
                 "'¥#29¢"';1SUB#1'~#65535"'~'#0¢#65535'"'~#1"~#0'¢.1
    ERROR: THE FIRST CHARACTER IS NOT "H"

    DO COME FROM '".2/'"'¥#1356¢"';1SUB#2'~#65535"'~'#0¢#65535'"~
                 "'¥#1356¢"';1SUB#2'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '.2~"'¥#1¢.1'~#1"'
    ERROR: THE SECOND CHARACTER IS NOT "E"

    DO COME FROM '".3/'"'¥#377¢"';1SUB#3'~#65535"'~'#0¢#65535'"~
                 "'¥#377¢"';1SUB#3'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".22/'"V.1¢.2"~#1'"~#0'¢'.3~"'¥#1¢.22'~#1"'
    ERROR: THE THIRD CHARACTER IS NOT "L"

    DO COME FROM '".4/'"'¥#383¢"';1SUB#4'~#65535"'~'#0¢#65535'"~
                 "'¥#383¢"';1SUB#4'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".23/'"V.22¢.3"~#1'"~#0'¢'.4~"'¥#1¢.23'~#1"'
    ERROR: THE FOURTH CHARACTER IS NOT "L"

    DO COME FROM '".5/'"'¥#378¢"';1SUB#5'~#65535"'~'#0¢#65535'"~
                 "'¥#378¢"';1SUB#5'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".24/'"V.23¢.4"~#1'"~#0'¢'.5~"'¥#1¢.24'~#1"'
    ERROR: THE FIFTH CHARACTER IS NOT "O"

    DO COME FROM '".6/'"'¥#177¢"';1SUB#6'~#65535"'~'#0¢#65535'"~
                 "'¥#177¢"';1SUB#6'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".25/'"V.24¢.5"~#1'"~#0'¢'.6~"'¥#1¢.25'~#1"'
    ERROR: THE SIXTH CHARACTER IS NOT COMMA

    DO COME FROM '".7/'"'¥#373¢"';1SUB#7'~#65535"'~'#0¢#65535'"~
                 "'¥#373¢"';1SUB#7'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".26/'"V.25¢.6"~#1'"~#0'¢'.7~"'¥#1¢.26'~#1"'
    ERROR: THE SEVENTH CHARACTER IS NOT SPACE

    DO COME FROM '".8/'"'¥#4160¢"';1SUB#8'~#65535"'~'#0¢#65535'"~
                 "'¥#4160¢"';1SUB#8'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".27/'"V.26¢.7"~#1'"~#0'¢'.8~"'¥#1¢.27'~#1"'
    ERROR: THE EIGHTH CHARACTER IS NOT "W"

    DO COME FROM '".9/'"'¥#574¢"';1SUB#9'~#65535"'~'#0¢#65535'"~
                 "'¥#574¢"';1SUB#9'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".28/'"V.27¢.8"~#1'"~#0'¢'.9~"'¥#1¢.28'~#1"'
    ERROR: THE NINTH CHARACTER IS NOT "O"

    DO COME FROM '".10/'"'¥#540¢"';1SUB#10'~#65535"'~'#0¢#65535'"~
                 "'¥#540¢"';1SUB#10'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".29/'"V.28¢.9"~#1'"~#0'¢'.10~"'¥#1¢.29'~#1"'
    ERROR: THE TENTH CHARACTER IS NOT "R"

    DO COME FROM '".11/'"'¥#353¢"';1SUB#11'~#65535"'~'#0¢#65535'"~
                 "'¥#353¢"';1SUB#11'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".30/'"V.29¢.10"~#1'"~#0'¢'.11~"'¥#1¢.30'~#1"'
    ERROR: THE ELEVENTH CHARACTER IS NOT "L"

    DO COME FROM '".12/'"'¥#375¢"';1SUB#12'~#65535"'~'#0¢#65535'"~
                 "'¥#375¢"';1SUB#12'~#65535"'~'#0¢#65535'"'~#1"~#0'¢
                 '".31/'"V.30¢.11"~#1'"~#0'¢'.12~"'¥#1¢.31'~#1"'
    ERROR: THE TWELFTH AND LAST CHARACTER IS NOT "D"

With today's information, you can already figure out that there are twelve
possible error exits, each one producing a message starting with "ERROR:",
and the "PLEASE GIVE UP" provides a way to signal that all went well.
For the rest, there will be future tutorials.

