CLC-INTERCAL Reference

... Statements

The statements are described in an order which minimises forward references. In other words, the first time you read this page go from beginning to end. For easy reference, an alphabetic list follows. See the description for the various statements to determine which compilers support them.

Table of contents:

Comments

Any statement which cannot be recognised is simply inserted in the compiled program. Executing this statement is very likely to be an error, however one can make sure the comments are ABSTAINed FROM (see below), so they won't be executed.

The following statement is initially ABSTAINed FROM (because of the word "NOT" as a prefix of "NOTE"):


	PLEASE NOTE THAT WE DO NOT KNOW WHAT WE ARE TALKING ABOUT
(in fact, this example contains two statements, but this is OK as they are both ABSTAINed FROM).

If a comment is executed, it is printed as an error message. For example,


	DO YOU REALISE THAT USING INTERCAL IS BAD FOR YOUR SANITY?
	PLEASE DO SOMETHING ELSE.
would print the first line and terminate the program (the second line is understood by the compiler as a separate statement, which does not get executed because the first line terminates the program).

Comments usually correspond to a splat code 0. Other error codes are listed in the chapter about Errors.

Calculate

This statement has the form of a register name, a left arrow (<-) and an expression. The effect is to assign the value of the expression to the register.

Examples:
DO .1 <- #3
DO ,1 SUB .1 SUB .2 <- .3~#3

If the left-hand side contains an array without subscripts, this statement will dimension the array (or redimension it, throwing away the old contents). In this case, it is possible to specify multidimensional arrays by including more than one expression, separated by the keyword "BY".

Example:
DO ,1 <- #3 BY #4 BY .1
CLC-INTERCAL 1.-94.-4 and newer allows to assign to constants, or indeed to any expression (when the compiler is sick). This result has always been possible using overloading, but it is now easier to achieve.

Examples:
DO #1 <- #3
DO .1 <- #4
assigns #3 to #1 and then assigns #4 to .3 (because the value of the "1" in .1 is now 3).

Examples:
DO .2 <- #1
DO #1 <- #3
DO #3 <- .2
swaps the values of #1 and #3.

Quantum INTERCAL allows the programmer to do and not-do the assignment at the same time using syntax DO .1 <- #2 WHILE NOT ASSIGNING TO IT. This is described in more detail in the chapter about Quantum INTERCAL.

IGNORE

The keyword "IGNORE" is followed by a list of registers, separated by intersection (+). After this, any attempt to modify the values of the registers will be silengly ignored, but any side effect will still happen, so if you try to WRITE IN an ignored register you discard some input, and if you assign an expression containing overloading you still execute the overloading; however, if you try to overload an IGNOREd register, this overloading won't be applied.

Note that you can IGNORE whole arrays, but not single subscripts.

The effect of IGNORE ceases when a REMEMBER lists the same registers.

Examples:
IGNORE .1 + ,1 + :3
IGNORE $49.99

Quantum INTERCAL allows the programmer to set the "ignore" state of a variable to both true and false symultaneously, for example:
IGNORE .1 + ,1 + :3 WHILE REMEMBERING THEM
IGNORE $49.99 WHILE REMEMBERING IT
This is described in more detail in the chapter about Quantum INTERCAL.

REMEMBER

The keyword is followed by a list of registers, separated by intersection (+). It undoes the effect of an IGNORE on those registers, so subsequent changes will affect them. It is not an error to REMEMBER a register which had not been IGNOREd.

It is possible to follow the list of registers with WHILE IGNORING THEM (or WHILE IGNORING IT if it's a single register): this produces a program which simultaneously remembers and ignores the registers: see the chapter about Quantum INTERCAL. (Note that IGNORING WHILE REMEMBERING is actually the same thing as REMEMBERING WHILE IGNORING so we didn't need to provide two separate statements; but we were in a generous mood when we implemented this).

ABSTAIN FROM

This is followed by either a label or a list of gerunds separated by intersection (+). The statement corresponding to that label, or all statements corresponding to the gerunds, will not be executed from now on (until a REINSTATE is executed).

It is not possible to ABSTAIN FROM GIVING UP. If you ABSTAIN FROM a label, and that happens to be a GIVE UP statement, this is silently ignored.

For example, the following program will assign 12 to register .1


	PLEASE ABSTAIN FROM (1)
    (1) DO ABSTAIN FROM CALCULATING + ABSTAINING
	DO .1 <- #12
	DO ABSTAIN FROM (2)
    (2) DO .1 <- #4
	PLEASE GIVE UP

It is possible to ABSTAIN FROM ABSTAINING. It is also possible to ABSTAIN FROM REINSTATING, although we do not recommend it.

The presence of a negative (NOT, N'T or ¬) before a statement will cause it to be initially ABSTAINED FROM, so the above program is equivalent to:


	DO NOT ABSTAIN FROM CALCULATING + ABSTAINING
	DO .1 <- #12
	DO NOT .1 <- #4
	PLEASE GIVE UP

Which in turn is the same as:


	DO .1 <- #12
	PLEASE GIVE UP

CLC-INTERCAL 1.-94 introduced ABSTAIN FROM COMMENTING, which ABSTAINs from anything the compiler finds unparseable. THere is a corresponding REINSTATE COMMENTING.

If you have a quantum computer, you can simultaneously ABSTAIN and REINSTATE a statement or a list of gerunds:


	PLEASE ABSTAIN FROM (1) WHILE REINSTATING IT
    (1) DO ABSTAIN FROM CALCULATING + ABSTAINING WHILE REINSTATING THEM
	DO ABSTAIN FROM CALCULATING WHILE REINSTATING IT
	PLEASE GIVE UP
This is described in more detail in the chapter about Quantum INTERCAL.

A recent improvement to the Quantum INTERCAL engine allows to ABSTAIN FROM QUANTUM COMPUTING, which would make all quantum statement behave like classical ones, and the corresponding REINSTATE QUANTUM COMPUTING. And of course, one can ABSTAIN FROM QUANTUM COMPUTING WHILE REINSTATING IT.

One last extension (in CLC-INTERCAL 0.05) allows to specify an expression instead of a label; and a statement template instead of a gerund. For example:


	DO ABSTAIN FROM REGISTER <- EXPRESSION
		      + REMEMBER REGISTER LIST
		      + IGNORE REGISTER LIST
is equivalent to:

	DO ABSTAIN FROM CALCULATING + REMEMBERING + IGNORING

However, statement templates give finer control than gerunds. For example, after:


	DO ABSTAIN FROM ABSTAIN FROM LABEL + REINSTATE GERUND LIST
an "ABSTAIN FROM (2)" or "REINSTATE ABSTAINING" would be ignored, but "ABSTAIN FROM REINSTATING" and "REINSTATE (3)" would be still executed.

REINSTATE

Followed by the same kind of things you can say after "ABSTAIN FROM", undoes the effects of ABSTAINING FROM these things. CLC-INTERCAL 0.05 or later allows an expression instead of a label, and a statement template instead of a gerund.

You can REINSTATE REINSTATING, and it does make sense - maybe you want to make sure that any REINSTATE which was ABSTAINED FROM by label is REINSTATEd. You cannot REINSTATE GIVING UP, not even by label.

Quantum program might wish to add WHILE ABSTAINING FROM IT (or WHILE ABSTAINING FROM THEM). See the chapter about Quantum INTERCAL.

CLC-INTERCAL 0.05 and newer allows to REINSTATE templates, with a syntax similar to ABSTAIN FROM templates.

CLC-INTERCAL 1.-94 allows to REINSTATE COMMENTING. You probably don't want to do that, but it's there if you need it. Note that there is no template corresponding to this gerund.

COME FROM

This is the main program control statement in CLC-INTERCAL. It is followed by either a label or an expression. When the execution reaches the label (or a label with the same value as the expression), it will run the current statement and then jump to the COME FROM. For example, this is a subroutine call, in which register .1 is used to hold the "return address" and register .2 to hold the "subroutine address":


	    DO .1 <- #1000
    (100)   DO .2 <- #100
	    PLEASE COME FROM .1
	    DO .1 <- #0
    ...
	    PLEASE COME FROM .2
	    DO .2 <- #0
    ...
    (1000)  DON'T PANIC

The assignment of #100 to .2 causes an immediate jump to the subroutine. At the end of the subroutine, after the no-op (DON'T PANIC does nothing because it is ABSTAINed FROM), the program jumps back to the COME FROM .1. We assign zero to the pointers just after use to avoid problems when the subroutine is called in more than one place.

It is an error to have multiple COME FROMs pointing at the same label (unless the thick compiler option is in operation). However, if all except one are ABSTAINed FROM, this is not a problem. So the above program can be rewritten as:


	    DO REINSTATE (101)
    (100)   DO .2 <- #100
    (101)   PLEASE DON'T COME FROM (1000)
	    DO ABSTAIN FROM (101)
    ...
	    PLEASE COME FROM .2
	    DO .2 <- #0
    ...
    (1000)  DON'T PANIC
or even without computed COME FROMs (although this requires to change the subroutine every time you add a call - this way of removing computed COME FROMs is best left to the optimiser):

	    DO REINSTATE (1001)
    (100)   DO REINSTATE (101)
    (101)   PLEASE DON'T COME FROM (1000)
	    DO ABSTAIN FROM (101)
	    DO ABSTAIN FROM (1001)
    ...
    (1001)  PLEASE DO NOT COME FROM (100)
    ...
    (1000)  DON'T PANIC

The simple program to implement a stack and allow recursive subroutines using this technique is left as an exorcism (sic) to the reader.

With recent versions of CLC-INTERCAL one can get away with repeating labels, so the subroutine can be called from several places without using computed COME FROMs:


	    PLEASE NOTE: CALL SUBROUTINE
	    DO REINSTATE (1001)
    (100)   DO REINSTATE (101)
    (101)   PLEASE DON'T COME FROM (1000)
	    DO ABSTAIN FROM (101)
	    DO ABSTAIN FROM (1001)
    ...
	    PLEASE NOTE: CALL SUBROUTINE
	    DO REINSTATE (1001)
    (100)   DO REINSTATE (102)
    (102)   PLEASE DON'T COME FROM (1000)
	    DO ABSTAIN FROM (102)
	    DO ABSTAIN FROM (1001)
    ...
    (1001)  PLEASE DO NOT COME FROM (100)
    ...
    (1000)  DON'T PANIC
All is needed is to have unique labels for the return statement, in this case (101) and (102) otherwise the subroutine won't know where to return.

CLC-INTERCAL 1.-94 introduces COME FROM GERUND (and NEXT FROM GERUND): for example:


        PLEASE COME FROM COMING FROM
causes an infinite loop because the statement keeps reexecuting (and COMING FROM itself!). Since there are runtime overheads associated with COME FROM GERUND, it must be requested by the compiler option come-from-gerund or by having the letter "g" somewhere in the suffix. And of course, templates can be used instead of gerunds, just like the ABSTAIN FROM and REINSTATE statements.

When the thick compiler option is in operation, multiple COME FROMs all pointing at the same label will cause the program to start as many threads as necessary so it gan go to all those places.

When using computed COME FROMs or computed labels, please remember that if any of the expressions have side effects (e.g. overloading), these side effects can appear in the most unexpected places. See for example the Hello, World program, which works by having each of the computed COME FROM setting up an overload to modify the way the other computed COME FROMs behave. It is slightly confusing.

The Quantum variant of COME FROM adds a "WHILE NOT COMING FROM THERE" at the end of the statement.

One final note, if the runtime detects something looking like an infinite loop, or if a statement COMEs FROM itself too often, it will introduce some extra delays or, if the INTERNET option is loaded, it will replace the loop with an operating system call to wait for network activity. This optimisation is done by the runtime, even when the optimiser is not loaded or disables.

NEXT

The keyword must be preceded by a label. It serves the function of the GO TO statement of other languages, and can also be used for subroutine calls. For this reason, it allow to write programs which look just like any other language, and this is a Bad Idea. CLC-INTERCAL considers any programs which use NEXT, FORGET or RESUME as obsolete, and will only run them if you use the next option or have an "n" somewhere in the suffix, or use the ick or 1972 compiler.

Beginning with CLC-INTERCAL 0.05, the label preceding "NEXT" can be replaced by an expression.

The effect of NEXT is to transfer control to the stated label, and also to save a return address in an internal stack. See FORGET and RESUME below for the rest of the story.

The Quantum version of NEXT adds "WHILE NOT NEXTING" at the end of the statement.

FORGET

Followed by an expression. It evaluates the expression, then removes that many return addresses from the stack managed by NEXT and RESUME. These addresses are simply discarded. If you want to use NEXT as a GO TO, you should FORGET #1 just afterwards so the stack does not overflow.

The Quantum version of FORGET adds "WHILE REMEMBERING" at the end of the statement; for compatibility with previous versions of CLC-INTERCAL, "WHILE NOT FORGETTING" can also be used.

RESUME

Followed by an expression. It evaluates the expression, then removes that many return addresses from the stack managed by NEXT and FORGET. After that, it jumps to the last return address it removed. So RESUME #1 is a normal return from subroutine, while RESUME #3 is equivalent to FORGET #2 followed by RESUME #1.

This is an example of subroutine call:


	    DO (1000) NEXT
    ...
    (1000)  DO ....
	    PLEASE RESUME #1

The Quantum version of RESUME adds "WHILE NOT RESUMING" at the end of the statement.

NEXT FROM

Like COME FROM, but it saves the return address, as a NEXT would do. It has the same syntax as COME FROM:


	PLEASE NEXT FROM (666)
	...
	DO RESUME #1

Just after executing the statement with label (666) the program jumps to the above fragment: at the end, it returns to the statement after the one with the label (666).

The Quantum version of NEXT FROM uses the syntax "WHILE NOT NEXTING FROM THERE"

STASH

Followed by a list of registers, it copies them to some secret place for safekeeping. You can stash whole arrays, but not single elements (well, you can always assign the element to a register and then STASH that). Note that not just the values are saved: the current BELONGS TO relation, the current overloading, and the current IGNORE/REMEMBER state are also saved. See RETRIEVE for the second half of the story.

RETRIEVE

Followed by a list of registers, it rummages through the STASH until it finds the most recent saved values of these registers, and restores them. These values are removed from the STASH, which effectively acts like a stack (yet another normal programming concept which has managed to creep into INTERCAL, sigh). After RETRIEVE, the register's value, BELONGS TO relation, overloading, and IGNORE/REMEMBER state are restored as they were before the corresponding STASH.

For example, the following program leaves .1, ;1 and ,1 SUB #1 unchanged:


	    PLEASE STASH .1 + ;1
	    DO .1 <- ,1 SUB #1
	    DO STASH .1
	    DO ,1 SUB #1 <- #0
	    DO ;1 SUB .1 <- #1
    ...
	    PLEASE RETRIEVE .1
	    DO ,1 SUB #1 <- .1
	    DO RETRIEVE .1 + ;1

Quantum version of STASH and RETRIEVE are of course available, by appending "WHILE NOT STASHING THEM" or "WHILE NOT RETRIEVING THEM".

GIVE UP

Finishes executing the program, presumably returning to saner things like a shell or perhaps JCL.

ABSTAIN FROM and REINSTATE do not have any effect on GIVE UP. This means that you can always GIVE UP, no matter how badly you've managed to screw up your program. Also, it means that DON'T GIVE UP is guaranteed to be a no-op.

The quantum version of GIVE UP appends "WHILE CONTINUING TO RUN" to the statement. What happens is that the program continues to run, the fact it also stops at the same time is irrelevant because it is not observable.

An interesting side-effect of the Quantum version is that if you ABSTAIN FROM QUANTUM COMPUTING and then GIVE UP WHILE CONTINUING TO RUN, you effectively GIVE UP; however if you REINSTATE QUANTUM COMPUTING then the above Quantum GIVE UP is a no-op. In other words, you can abstain from giving up, using this trick, by calling it REINSTATE QUANTUM COMPUTING.

READ OUT

Followed by a list of expressions, which are allowed to evaluate to numbers or to whole arrays, will read whatever came out of these expressions to the standard output. See the chapter on Input/Output. If an element of the list evaluates to a whirlpool register, this changes the destination for the subsequent elements.

Since the effects of a READ OUT are observable. there is no Quantum READ OUT. Either you do it, or you don't.

WRITE IN

Followed by a list of expressions, which are allowed to evaluate to numbers, registers or whole arrays, this will get some data from standard input and tries to make the data go into the expressions. For example:


	PLEASE WRITE IN .1 + #2
will try to get two separate numbers from standard input, store the first one in register .1 and use the second one to alter the value of the constant #2. See the chapter on Input/Output. If any of the elements evaluates to a whirlpool register, this changes the place the subsequent elements will try to obtain the data from.

The quantum WRITE IN (which appends "WHILE NOT WRITING THEM" to the statement) always consumes some input, except that it assigns it to variables while at the same time not assigning it. This is not the same as executing the WRITE IN while not executing it, which would require the input to be consumed while at the same time not being consumed, which would be impossible as the internal quantum state could be observed.

ENSLAVE

Followed by two registers (without subscripts, if arrays), using the form:


	DO ENSLAVE .1 TO ,1
it sets the BELONGS TO relation between the first and the second. It is not an error if the first register is already a slave, although it can be confusing. See the chapter on Belongs TO.

The Quantum version of this statement appends "WHILE LEAVING IT FREE"

FREE

Followed by two registers (without subscripts, if arrays), using the form:


	DO FREE .1 FROM ,1
it removes the BELONGS TO relation between the first and the second. It is an error if the first register was not a slave of the second. If the first register BELONGed TO more than one register, the other owners remain unchnanged. See the chapter on Belongs TO.

The Quantum version of this statement appends "WHILE LEAVING IT IN SLAVERY"

STUDY

Followed by a subject number, a lecture label, and a class name, using a format like:


	DO STUDY #2 AT (1030) IN CLASS @4
It advertise that the lecture is available. See the chapter on Classes and Lectures.

Beginning with CLC-INTERCAL 0.05, the subject number and the label can be replaced by expressions.

The Quantum version of this statement appends "WHILE NOT STUDYING IT"

ENROL

Followed by a register (without subscripts, if an array) and a list of subjects, using a format like:


	DO ENROL .2 TO LEARN #1 + #4 + #5

It looks for a class where these subjects are taught, and makes a note that the register is now a student there. It is an error if no class is found which teaches these subjects, or if there is more than one eligible class. The latter case results in a CLASS WAR error. See the chapter on Classes and Lectures.

Beginning with CLC-INTERCAL 0.05, the subject numbers can be specified as expressions and need not be constant.

The Quantum version of this statement appends "WHILE NOT ENROLLING"

LEARNS

Preceded by a register (without subscripts, if an array) and followed by a subject number, as in:


	DO .2 LEARNS #4

The register must have ENROLled in a class which teaches that subject. The effect is to go to the lecture. The class will be temporarily ENSLAVed to the register. This can be used to replace what other languages call "self" or "this". See the chapter on Classes and Lectures.

Beginning with CLC-INTERCAL 0.05, the subject number can be specified as an expression.

The Quantum version of this statement is specified with "WHILE NOT LEARNING IT"

FINISH LECTURE

Used in lectures to return to the statement following the last LEARNS. See the chapter on Classes and Lectures.

The Quantum version of this statement is specified with "WHILE CONTINUING IT"

GRADUATES

Preceded by a register (if an array, without subscripts), it removes it from the list of students of all classes. The effect is that the register cannot LEARN anything after that, unless he ENROLs again. See the chapter on Classes and Lectures.

The Quantum version of this statement is specified with "WHILE REMAINING A STUDENT"

CONVERT

Followed by one statement template, the keyword "TO", and another statement template. At runtime, the meaning of the first statement is changed into the meaning of the second. In most back ends, this will be implemented by keeping a list of code references (or pointer to functions or whatever), and changing them as needed. The statements must be "compatible", i.e. their syntactic definition must use the same terminals. For example, the statement ABSTAIN FROM can contain wither a single LABEL or a GERUND LIST. In the latter form, can only be converted to a REINSTATE. In the form with LABEL, it can be converted to COME FROM, NEXT, or REINSTATE. The statements to do all these conversions are:


	DO CONVERT ABSTAIN FROM GERUND LIST TO REINSTATE GERUND LIST
	DO CONVERT ABSTAIN FROM LABEL TO COME FROM LABEL
	DO CONVERT ABSTAIN FROM LABEL TO LABEL NEXT
	DO CONVERT ABSTAIN FROM LABEL TO REINSTATE LABEL

Of course, if the come-from-gerund option is in effect, it is also possibe to:


	DO CONVERT ABSTAIN FROM GERUND LIST TO COME FROM GERUND LIST

There is a quantum version of this statement, obtained adding the string "WHILE LEAVING IT UNCHANGED" at the end. This has the effect of doing the conversion but at the same time not doing it. This is described in more detail in the chapter about Quantum INTERCAL.

This statement was introduced in CLC-INTERCAL 0.05.

SWAP

Followed by one statement template, the keyword "AND", and another statement template. At runtime, the meaning of the first statement is changed into the meaning of the second, and vice versa. In most back ends, this will be implemented by keeping a list of code references (or pointer to functions or whatever), and changing them as needed. The statements must be "compatible", i.e. their syntactic definition must use the same terminals. For example, "CALCULATE" has two terminals, a REGISTER and an EXPRESSION. The other statement which has the same terminals is LEARNS. Therefore, they can be swapped. The two following statements both do the same (and undo each other):


	 DO SWAP REGISTER <- EXPRESSION AND REGISTER LEARNS EXPRESSION
	 DO SWAP REGISTER LEARNS EXPRESSION AND REGISTER <- EXPRESSION

There is a quantum version of this statement, obtained adding the string "WHILE LEAVING THEM UNCHANGED" at the end. This has the effect of doing the swapping but at the same time not doing it. This is described in more detail in the chapter about Quantum INTERCAL.

This statement was introduced in CLC-INTERCAL 0.05

CREATE

This is the most powerful statement of CLC-INTERCAL, and, by necessity, the most complex. The syntax is described in detail in the chapter about parsers. It extends the C-unlike postprocessor (see the convert and swap statements) in such a way that a complete compiler can be written out of CREATE statements. In fact, CLC-INTERCAL 1.-94 and newer are written this way.

This statement was introduced in CLC-INTERCAL 1.-94.

The Quantum version of this statement appends "WHILE NOT CREATING IT"

DESTROY

This statement undoes the effect of a CREATE. Note that since the compiler itself is just a big list of CREATE statement you can also remove bits of the compiler you don't like. The syntax is described in detail in the chapter about parsers.

This statement was introduced in CLC-INTERCAL 1.-94.

The Quantum version of this statement appends "WHILE NOT DESTROYING IT"

WHILE

Preceded by a statement, and followed by another one, executes the two simultaneously. The first statement acts as a "loop control" for the second, which is repeated as many times as needed. For example:


	PLEASE STUDY #1 AT (1000) IN CLASS @1
	DO ENROL .1 TO LEARN #1
	DO .1 LEARNS #1 WHILE READ OUT .1

Would keep reading out the value of .1 until the lecture is finished. This might or might not cause disruption to the lecture.

The first statement can be replaced by an expression, in which case the WHILE statement is called "event statement". If the expression can be evaluated, the statement is executed and the program continues as normal. If the expression produces an error, the WHILE is kept in suspended animation until it is possible to execute it. For example:


	DO ,1 <- #2
	PLEASE DO ,1 SUB #1 #1 WHILE ,1 SUB #1 #1 <- #5
	DO ,1 SUB #1 <- #2
	DO ,1 <- #2 BY #2
	DO .1 <- ,1 SUB #1 #1
	DO READ OUT .1

Will read "V". This is because the ",1 SUB #1 #1" produces an error (too many subscripts), but is retried as soon as ,1 is redimensioned, and causes #5 to be assigned to ",1 SUB #1 #1" after dimensioning but before assigning to .1

This statement was introduced in CLC-INTERCAL 0.05.

Note that there isn't a Quantum version of this statement, although its two sub-statements can be quantum, for example:


	DO ABSTAIN FROM (1) WHILE REINSTATING IT
	WHILE
	COME FROM (2) WHILE NOT COMING FROM THERE

STEAL and SMUGGLE

These statements are only available after loading the INTERNET option. Since CLC-INTERCAL 1.-94.-2 they also require the optional package CLC-INTERCAL-INET to be installed.

The statement is followed by a list of variables, optionally ON and a Process ID and optionally FROM and an IP address. For example:


	DO STEAL .1 ON #1234 FROM :1
	DO STEAL .1 ON #1234
	DO STEAL .1 FROM :1
	DO STEAL .1

When both a PID and an IP address are specified (first example), and the IP address is a IPv4 or IPv6 unicast address, the program will first connect to a theft server on that IP address, using TCP and default INTERNET port, it asks that theft server how to connect to the required PID, then opens a second connection to talk directly to that program. Once connected, it coordinates with the other program to perform the STEAL or SMUGGLE operation, as described below. Note that the "other" program could actually be the same program if it specifies its own PID and a local IP address: this is fully supported.

If the statement specifies an IP address and it turns out to be IPv4 broadcast address or an IPv6 multicast group address, the program will first attempt to locate a theft server by sending a query out (using IPv4 broadcast or IPv6 multicast as appropriate), asking for any server who happens to have that particular PID running to reply, then waits to see who answers, and picks a random IP address from the ones who answered: then it proceeds as though that random IP address had been specified in the first place.

If the statement does not specify an IP address, by omitting the FROM (second example), the program will send out both IPv4 broadcast and IPv6 multicast queries, as specified by the configuration, waits for an answer, and proceeds as described in the previous paragraph.

If the statement does not specify a PID (third and fourth example), the program will first determines an IP address as described above, with the difference that any broadcast or multicast queries will not include a specifid PID, so all nodes running any INTERNET-enabled INTERCAL programs will reply. After selecting a particular IP address from the replies, the program will select a random PID from these running on that particular IP address (this requires a connection to the theft server on that particular node, but instead of asking how to communicate with a particular PID, it will ask to pick one at random and reply with its details). It is possible for the implementation to optimise the network usage when this description implies multiple network connections, but a single one could return all the necessary information, so the programmer must not make assumptions about the exact network activity resulting from the execution of a STEAL or SMUGGLE.

Stealing a variable means doing a destructive copy, so that the vistim can no longer use it, while the thief gets the original value. For example, suppose the following program runs as Process ID #666 on IP address 10.0.0.1:


	DO .1 <- #2
    (2) PLEASE COME FROM (.1)
	DO READ OUT .1
	DO GIVE UP
The second statement is recognised by runtime as an infinite loop when it gets executed, and automatically replaced with a wait for a network connection or some other event which may cause register .1 to change its value, so this is a good way to wait for such events.

Now consider the following program running on some other computer:


	DO STEAL .1 ON #666 FROM #12288 ¢ #1
	PLEASE READ OUT .1
	DO GIVE UP

This produces "II", because it goes to get the variable .1 from the previous program (#12288 ¢ #1 is 10.0.0.1; do the calculation to convince yourself that this is the case).

Meanwhile, the first program produces NIHIL and terminates: this is because register .1 has been stolen, so it's now reset to its initial value (#0). This causes the COME FROM to stop executing, and the READ OUT to produce NIHIL.

If a register is IGNOREd by the victim it cannot be stolen. This is because stealing a register modifies it. However, the SMUGGLE statement, which has identical syntax, allows to copy an IGNOREd register, of course without modifying it. It is a runtime error to STEAL an IGNOREd register, or to SMUGGLE one which is not IGNOREd.

Note that the thief is free to IGNORE or REMEMBER a register before stealing or smuggling it: the theft will always succeed, but the subsequent assignment of the value to the thief's variables is controlled by the thief's IGNORE state for the register. For example, the code:


	PLEASE IGNORE .1
	DO STEAL .1 ON #666 FROM #12288 ¢ #1
would effectively throw away the value of .1 in the program running as PID 666 on 10.0.0.1: the theft succeeds, so that program will no longer be able to access the value of .1, but the thief is ignoring the register, so the value is thrown away.

STEAL and SMUGGLE have Quantum counterparts, which are specified with "WHILE NOT STEALING IT" and "WHILE NOT SMUGGLING IT" (or "THEM"). Like Quantum WRITE IN, the theft always happens, but the assignment of the result happens while not happening.

The next section suggests a way to obtain IP addresses and process IDs

CASE

This statement is only available after loading the INTERNET option. Since CLC-INTERCAL 1.-94.-2 it also requires the optional package CLC-INTERCAL-INET to be installed.

This statement is followed by an expression, IN and a list of case elements (with the form expression THEN statement) separated by OR, and optionally followed by ESAC if one wants to type a bit more. For example:


	DO CASE :1 IN
	   .2 THEN READ OUT ,3
	OR
	   .3 THEN READ OUT .2
	OR
	   .4 THEN GIVE UP
	ESAC
It executes a generic network look-up and assigns the results to the variables indicated in the case elements; after that, it executes all the statements in sequence, skipping any which are ABSTAIed FROM.

The network look-up performed depends on the type of the expression. If it is an array, it is converted to characters (as if you READ it OUT) and used as a name to perform a DNS look-up; if it is a number, it is interpreted as an IP address; if it corresponds to an IPv4 broadcast or IPv6 multicast address, the system will send a query on the specified address and waits a few seconds for replies: the encoded IP addresses of everything which replied will be used as result of the look-up; if the number corresponds to a unicast address, the program queries the specified computer and obtains a list of Process IDs running INTERNET programs as a result of the look-up. Note that INTERCAL programs which have not loaded the INTERNET extension are not reported by this query.

The list of numbers returned by a query are then assigned to each of the expressions mentioned in a case element: if there are more numbers returned than there are expressions, an implementation-defined subset will be used; if there are more expressions than numbers to assign to them, an implementation-defined subset of the registers will not be assigned to. At the time of writing (1.-94.-2.1), the implementation does not specify what values are discarded if there are too many of them, but it does specify that the registers are assigned in order, so that the unassigled ones will all be at the end.

If any of the expressions evaluates to an array (tail or hybrid), the array elements are assigned in order as though they had been specified as separate expressions; if the array is not dimensioned, a splat occurs.

Consider the statement:


	DO CASE #0 IN
	   :1 THEN CASE :1 IN
	      .2 THEN STEAL ,1 ON .2 FROM :1
or, for better legibility:

	DO CASE #0 IN
	   :1 THEN CASE :1 IN
	      .2 THEN STEAL ,1 ON .2 FROM :1
	   ESAC
	ESAC
This is the internal implementation of DO STEAL ,1 - first, it broadcasts on all local network interfaces to get a list of IP addresses (#0 is considered a broadcast address by the CASE statement). Then a random one is selected (because there is only one case element) and assigned to :1. Then the statement inside the CASE is executed - this is another CASE, his time using the IP address returned by the first one to get a list of Process IDs. Again, there is only one element, so a random one is selected and assigned to .2 - finally, the STEAL statement uses the IP address and Process ID. The only real difference between this example and a simple DO STEAL .1 is that this example also keeps the random IP and PId used (in :1 and .2 respectively), which may be used by the program to do something else, while the implicit CASE executed by STEAL when ON or FROM are not specified does not save these numbers.

Of course there is also a Quantum CASE statement: the syntax is slightly unusual: DO CASE expression WHILE NOT CASING IT IN register THEN statement [OR register THEN statement]... [ESAC], for example:


	DO CASE :1 WHILE NOT CASING IT IN
	   .2 THEN READ OUT ,3
	OR
	   .3 THEN READ OUT .2
	OR
	   .4 THEN GIVE UP
The operation is the obvious one: the look-up, assignments and sub-statements are all executed while at the same time none of them is executed.

To improve the program's legibility when a CASE statement is nested inside another, it is possible to terminate the list of case elements with the keyword ESAC. This closes the innermost CASE. For example:


	DO CASE #0 IN
	   :1 THEN CASE :1 IN
	      .1 THEN STEAL ,1 ON .1 FROM :1
	   OR
	      .2 THEN READ OUT .2
	   ESAC
	OR
	   :2 THEN WRITE IN :3
	ESAC
(And, yes, it's a rather meaningless program, but it shows the syntax). A seasoned programmers will simplify this to the more compact:

	DOCASE#0IN:1THENCASE:1IN.1THENSTEAL,1ON.1FROM:1OR.2THENREADOUT.2ESACOR:2THENWRITEIN:3
The final ESAC has also been omitted as it was not necessary in such a simple and legible line