thumb|Jimbo Lyon, az INTERCAL egyik szerzője Az INTERCAL egy ezoterikus programozási nyelv, amit Don Woods és James M. Lyon, a Princetoni Egyetem hallgatói alkottak 1972-ben. A korabeli programnyelvek, nyelvtervek különböző jellemzőit, és az 1960-as évek jelöléseit parodizálja.

Jelenleg két támogatott verziója létezik: a C-INTERCAL, amit korábban Eric S. Raymond gondozott, és a CLC-INTERCAL Claudio Calvelli gondozásában.

Története A szerzők eredeti leírása szerint:

A fordító teljes neve „Compiler Language With No Pronounceable Acronym” lett volna, amit nyilvánvaló okok miatt INTERCAL-ra lett lerövidítve.

Az eredeti implementáció EBCDIC karakterkészletet és lyukkártyákat használt. Az ASCII-t használó számítógépeken való futáshoz két karaktert kicseréltek: a ¢-t $-ra, ami a szoftver emelkedő költségét szimbolizálja a hardverhez viszonyítva, és a ∀-t ?-re, ami az átlagember reakcióját fejezi ki, amikor először találkozik a kizáró vaggyal. A C-INTERCAL újabb verzióiban a régebbi operátorok is elérhetők szinonimaként; az INTERCAL programok lehetnek ASCII, Latin-1, vagy UTF-8 kódolásúak is.

Részletek A nyelvet úgy tervezték, hogy különbözzön más programozási nyelvektől. A legtöbb nyelvben használt operátorok szintaxisa rejtélyes és redundáns. A manuál szerint:

Ismert és jól bemutatható tény, hogy akinek a munkája érthetetlen, azt nagyra becsülik. Például a 65536 eltárolása egy 32 bites változóban a következő módon tehető meg a legegyszerűbben:

DO :1 <- #0¢#256

amire minden értelmes programozó azt mondaná, hogy abszurd.

A nyelv több más esztétikai eszközt is tartalmaz: utasításokat, mint a "READ OUT" (olvasd ki), "IGNORE" (ignoráld), "FORGET" (feledd el), és módosítókat, mint a "PLEASE" (kérem). Ha ez utóbbiból túl kevés van, akkor a fordító hibát jelez, mert a program nem elég udvarias. Ha túl sok van, akkor is hibát kapunk, mert túl udvarias. Habár az első fordító is így működött, akkor még dokumentálatlan maradt.

A nyelv akaratlagos szószátyársága ellenére Turing-teljes: elegendő memóriával bármit meg lehet benne oldani, amire az univerzális Turing-gép képes. Azonban a legtöbb implementáció nagyon lassú. Egy 65536-ig minden prímet kiszámoló Eratoszthenész szitáját egy Sun SPARCstation 1-en tesztelték. C-ben kevesebb, mint fél másodpercig tartott; ugyanez a program INTERCAL-ban implementálva több, mint tizenhét órán át futott.

Az INTERCAL kézikönyv szerint a tervezésben fontos volt, hogy ne hasonlítson semmilyen más nyelvre. Itt gondolhattak akár a vezérlési szerkezetekre, akár az adatok feldolgozására. Ebben a tervezők elég sikeresnek bizonyultak. A BESM-6 szovjet számítógéptípus (megjelent 1967-ben) gépi kódja tartalmaz egy SELECT-nek megfelelő utasítást.

Dokumentáció thumb|A "select" operátor működését szemléltető "circuitous diagram" az INTERCAL Reference Manualból A kézikönyv sok paradox, nonszensz, vagy más humoros megjegyzést tartalmaz:

Vigyázat! Semmilyen körülmények között ne tévessze össze a mesh és az interleave operátort, kivéve azokat a körülményeket, ahol össze lehet őket téveszteni!

A manuál tartalmaz egy mandulát is; ahogy a lábjegyzetben kifejtik: Mivel a kézikönyvekben szokott lenni függelék (appendix, ami vakbelet is jelent), ezért úgy döntöttünk, hogy ez a manuál egy másik eltávolítható szervet tartalmazzon.

A kézikönyv minden nem alfanumerikus karakternek új, szokatlan nevet ad; az egyszerű idézőjel (') neve sparks, a dupláé (") rabbit ears (nyúlfül). Az egyetlen kivétel az ampersand (&); ahogy a Jargon File írja: Mi lehet ennél hülyébb? A legtöbb nyelvben használt = jelet (half mesh, fél háló) az INTERCAL-ban balra mutató nyíl (<-) helyettesíti, ami egy angle-ből (szög) és egy wormból (kukac) épül fel.

Szintaxis Az input (a WRITE IN utasítás) és az output (a READ OUT utasítás) nem használják a megszokott formákat; az INTERCAL-72-ben a WRITE IN az angolul kiírt számjegyeket támogatja, mint SIX FIVE FIVE THREE FIVE (65535) és a READ OUT római számokat ír ki. Az újabb verzióknak saját I/O rendszerük van.

A kommenteket a megfordított utasításnevek jelzik a NOT vagy a N'T egyikével bővítve. Az ezek után írottakat alapból nem veszi figyelembe (ABSTAIN). Ha egy sor szintaktikailag hibás, akkor a fordító szintén figyelmen kívül hagyja, és a hiba futás közben jelenik meg. Adattípusok Az INTERCAL-72 4 adattípust ismer: a 16 bites egészet (reprezentációja . 'spot' pötty), a 32 bites egészet (jele :, 'twospot' kétpötty), a 16 bites egészek tömbje (, 'tail' farok), és a 32 bites egészek tömbje (;, 'hybrid', hibrid). Mindegyik típus számára 65535 változó áll rendelkezésre, például a 16 bites egészeket a .1-től a .65535-ig terjedő változók tárolhatják. Mindezek a változók veremként működnek; a betevés neve INTERCAL-ban STASH, a kivevésé RETRIEVE, ami támogatja a bonyolultabb adatszerkezeteket is. Mindezek az adatszerkezetek az újabb implementációkban is megtalálhatók apróbb módosításokkal. A TriINTERCAL például hármas számrendszerben tárolja az adatokat, így a 16 bites számok helyett 10 trites számokat használ. A CLC-INTERCAL más adatszerkezetekkel is bír, mint 'classes and lectures' (osztályok és órák), amelyek az újabb típusok létrehozása helyett azt teszik lehetővé, hogy az eddigi szerkezetek még több információt tárolhassanak. A tömbök dimenzióját skalárszerű értékadással lehet megadni. A konstansok jele a # ('mesh', háló), amit maga a konstans követ, tízes számrendszerben; csak a 0 és a 65535 közötti értékeket vehetik fel. Operátorok Az INTERCAL-72 öt operátort tartalmaz; az egyes implementációk ezeket másként jelölik. Egyes implementációkban több jel is használható:

+ INTERCAL operators Operátor INTERCAL-72 karakterek Atari karakterek C-INTERCAL karakterek CLC-INTERCAL karakterek INTERLEAVE / MINGLE c backspace / $ ¢, $, c backspace / ¢ SELECT ~ ~ ~ ~ AND & & & & OR V V V V XOR V backspace - ? V backspace -, ?, ∀ V backspace -, ¥

Szemben a legtöbb nyelvvel az AND, az OR és a XOR unáris operátorok, amelyek a következő módon működnek: az eredmény legszignifikánsabb bitje az argumentum legszignifikánsabb és a legkevésbé szignifikáns jegyéből keletkezik az eredmény második legszignifikánsabb bitjét a legszignifikánsabb és az azt követő bitjéből számítják ki az eredmény harmadik legszignifikánsabb bitje az argumentum második legszignifikánsabb és az azt követő bitjéből adódik és így tovább

Az operátor helye a változót jelölő pont vagy kettőspont után, a számjelölés előtt van, vagy a csoportosító jelek közül az elsőt követi; azaz egy karakterrel hátrébb áll, mint például a C-ben.

A SELECT és az INTERLEAVE, ami MINGLE néven is ismert, infix bináris operátorok. A SELECT veszi az első argumentumának azokat a bitjeit, amelyek 1-ek, és a második argumentumából kitörli az ezeken a helyeken álló nullákat. Az így kapott számot eltolja a kevésbé szignifikáns irányba, és nullákkal tölti ki. Például az 51 (110011) SELECT 21 (10101) eredménye 5 (101). A MINGLE felváltva veszi a biteket az első és a második operandusból úgy, hogy az eredmény utolsó jegye a második argumentum utolsó jegye legyen.

Az operátorok között nincs precedencia; szükség esetén csoportosító jelek használhatók. Ezek a ' és a ", amelyek a megfelelőjükkel állnak párba. A programozó felelőssége, hogy a jelölés egyértelmű legyen. Vezérlési szerkezetek Az INTERCAL programok a DO, a PLEASE vagy a PLEASE DO szavakkal kezdődnek. Ezek mind ugyanazt jelentik, de túl gyakori alkalmazásuk miatt a fordító hibát jelez, amit az INTERCAL-72-ben nem dokumentáltak, de a C-INTERCAL kézikönyve leírja. Jöhetnek ezek a szavak fordítva is, a NOT vagy a N'T hozzáfűzésével. A Backtracking INTERCAL ezek mellett megengedi a MAYBE szó használatát, ami egy választási pontot vezet be. Ez kombinálható a fenti lehetőségekkel. Az azonosító elé írható zárójelben egy sorszám; utána megadható, hogy a sor milyen százalékos eséllyel hajtódjon végre: ennek formája %50. Az alapértelmezett a 100%.

Az INTERCAL-72-ben a fő vezérlési szerkezetek a NEXT, RESUME, és a FORGET. A DO (sor) NEXT leágazik a megadott sorra azzal, hogy megjegyzi azt a sort, ami végrehajtódott volna, ha nem lenne NEXT a hívási vermen. Itt a DO helyett más azonosítók is használhatók. A DO FORGET kifejezés eltávolítja a kifejezést a hívási veremből, aminek a kapacitása 80. Hasonlóan cselekszik a DO RESUME is, de utána visszaugrik az utoljára megjegyzett sorra.

A C-INTERCAL tartalmazza a COME FROM utasítást is, aminek formája DO COME FROM (sor); a CLC-INTERCAL és az újabb C-INTERCAL számított COME FROMot (DO COME FROM kifejezés) is tartalmaz, meg a NEXT FROMot, ami ugyanaz, mint a COME FROM, de elmenti a visszatérési címet a NEXT STACKre.

A COME FROM a GOTOhoz hasonlóan, de azzal ellentétes irányban működik. Amikor a vezérlés eléri a megadott címet, az adott sor végrehajtása után ide ugrik. Ha több COME FROM hivatkozza ugyanazt a sort, akkor az eredmény lehet érvénytelen, viselkedhet nem determinisztikusan, végrehajtódhat egymás után prioritás szerint, vagy végrehajtódhat párhuzamosan, mint a Threaded Intercalban.A COME FROM működése

További működést befolyásoló tényezők az INTERCAL-72-ben az IGNORE és a REMEMBER változók kiiktatására és visszakapcsolására szolgálnak. Emiatt kimaradnak azok a sorok, ahol a változó szerepel. A sorok megjegyzésbe tételére és a megjegyzés végének jelzésére való az ABSTAIN és a REINSTATE, amelyek utasítástípusokra is vonatkozhatnak.

Példaprogramok Hello, world! A hagyományos "Hello, world!" program C-ben:

#include <stdio.h>

int main() { printf("Hello, world!\n"); return 0; }

Ugyanez INTERCALban:

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 DO ,1 SUB #7 <- #48 PLEASE DO ,1 SUB #8 <- #22 DO ,1 SUB #9 <- #248 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

ROT13-program

(10) PLEASE DON'T GIVE UP (1) DO .2 <- '?.1$#64'~'#0$#65535' DO .2 <- '&"'.1~.2'~'"?'?.2~.2'$#32768"~"#0$#65535“'"$".2~.2“'~#1 DO .3 <- '?#91$.1'~'#0$#65535' DO .3 <- '&"'#91~.3'~'"?'?.3~.3'$#32768"~"#0$#65535“'"$".3~.3“'~#1 DO (11) NEXT DO (2) NEXT DO (12) NEXT (11) DO (13) NEXT PLEASE FORGET #1 DO (12) NEXT (13) DO (14) NEXT PLEASE FORGET #2 DO (12) NEXT (14) DO STASH .1 DO .1 <- .3 DO (1000) NEXT DO .1 <- .3 DO .2 <- #1 PLEASE DO (1000) NEXT DO RETRIEVE .1 PLEASE RESUME .3 (12) PLEASE FORGET #1 DO .2 <- '?.1$#96'~'#0$#65535' DO .2 <- '&"'.1~.2'~'"?'?.2~.2'$#32768"~"#0$#65535“'"$".2~.2“'~#1 DO .3 <- '?#123$.1'~'#0$#65535' DO .3 <- '&"'#123~.3'~'"?'?.3~.3'$#32768"~"#0$#65535“'"$".3~.3“'~#1 PLEASE DO (15) NEXT PLEASE DO (3) NEXT DO (16) NEXT (15) DO (17) NEXT PLEASE FORGET #1 DO (16) NEXT (17) DO (18) NEXT PLEASE FORGET #2 DO (16) NEXT (18) PLEASE STASH .1 DO .1 <- .3 DO (1000) NEXT DO .1 <- .3 DO .2 <- #1 DO (1000) NEXT PLEASE RETRIEVE .1 PLEASE RESUME .3 (16) PLEASE FORGET #1 DO RESUME #1 (2) DO .2 <- #65 DO (1010) NEXT PLEASE .1 <- .3 PLEASE .2 <- #13 DO (1000) NEXT DO STASH .3 DO .1 <- .3 DO .2 <- #26 DO (1040) NEXT DO .1 <- .3 DO (1030) NEXT DO .2 <- .3 DO RETRIEVE .3 DO .1 <- .3 DO (1010) NEXT DO .1 <- .3 DO .2 <- #65 DO (1000) NEXT DO .1 <- .3 DO RESUME #1 (3) DO .2 <- #97 DO (1010) NEXT DO .1 <- .3 DO .2 <- #13 DO (1000) NEXT DO STASH .3 DO .1 <- .3 DO .2 <- #26 DO (1040) NEXT DO .1 <- .3 DO (1030) NEXT DO .2 <- .3 DO RETRIEVE .3 DO .1 <- .3 DO (1010) NEXT DO .1 <- .3 DO .2 <- #97 DO (1000) NEXT DO .1 <- .3 DO RESUME #1 DO COME FROM (10) DO .4 <- #0 DO .5 <- #0 DO STASH .4 + .5 DO ,1 <- #1 DO COME FROM (33) DO WRITE IN ,1 DO .1 <- ,1 SUB #1 DO (31) NEXT PLEASE DO .6 <- #1 PLEASE DO (34) NEXT (32) PLEASE RESUME '?.1$#256'~'#256$#256' (31) DO (32) NEXT DO FORGET #1 DO .6 <- #0 PLEASE DO (34) NEXT (33) DON'T GIVE UP (34) DO .6 <- "?!6'$#1"~#3 DO (40) NEXT DO GIVE UP (40) DO (41) NEXT PLEASE FORGET #1 DO (42) NEXT (41) DO RESUME .6 (42) DO FORGET #1 DO RETRIEVE .4