INTERCAL (programozási nyelv)
![](http://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Jimbo_Lyon.jpg/220px-Jimbo_Lyon.jpg)
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,[1] é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,[2] és a CLC-INTERCAL Claudio Calvelli gondozásában.[3]
Története
[szerkesztés]A szerzők eredeti leírása szerint:[4]
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.[4] 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.[5]
Részletek
[szerkesztés]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.[4]
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.[6]
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.[7]
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.[8]
Dokumentáció
[szerkesztés]![](http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/INTERCAL_Circuitous_Diagram.svg/220px-INTERCAL_Circuitous_Diagram.svg.png)
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
[szerkesztés]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.[4] Az újabb verzióknak saját I/O rendszerük van.[3][6]
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.[4]
Adattípusok
[szerkesztés]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.[4] 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.[6] 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.[3] 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.[4]
Operátorok
[szerkesztés]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ó:
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
[szerkesztés]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.[6] Jöhetnek ezek a szavak fordítva is, a NOT vagy a N'T hozzáfűzésével.[4] A Backtracking INTERCAL ezek mellett megengedi a MAYBE szó használatát, ami egy választási pontot vezet be.[9] 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%.[4]
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.[4]
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.[3]
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.[10]
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.[4]
Példaprogramok
[szerkesztés]Hello, world!
[szerkesztés]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
[szerkesztés] (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
DO .2 <- .4
DO (1000) NEXT
DO .4 <- .3~#255
DO .3 <- .4
DO STASH .4
DO .1 <- .3
DO (1) NEXT
DO .3 <- !1~#15'$!1~#240'
DO .3 <- !3~#15'$!3~#240'
DO .2 <- !3~#15'$!3~#240'
DO .1 <- .5
DO (1010) NEXT
DO .5 <- .2
DO ,1 SUB #1 <- .3
PLEASE READ OUT ,1
PLEASE RESUME #1
Nyelvjárások
[szerkesztés]Az eredeti Woods–Lyon INTERCALban nagyon korlátozottak voltak a be- és a kiviteli eszközök: beolvasni csak angol számjegyeket tudott, kiírni csak kiterjesztett római számokat. Az Atari implementációról a manuál is megemlékezik, mint ami az eredetitől leginkább a kódolásban különbözik.[4]
Az interneten elérhető C-INTERCAL implementáció népszerűvé tette a nyelvet az ezoterikus programnyelvek iránt érdeklődők körében.[6] A C-INTERCAL bevezetett néhány új eszközt, mint a COME FROM utasítást, és a Turing-szövegmodellen alapuló be- és kivitelt.[6]
A C-INTERCAL implementálói alkották a TriINTERCALt, ami a hármas számrendszeren alapul, és általánosítja az operátorokat.[6]
Egy újabb variáns a Threaded Intercal, ami kiterjeszti a COME FROM funkcionalitását a többszálúság támogatására.[11]
Vélemények
[szerkesztés]Az "A Box, Darkly: Obfuscation, Weird Languages, and Code Aesthetics" cikk az INTERCALt az "Abandon all sanity, ye who enter here: INTERCAL" (INTERCAL: ki itt belépsz, hagyj fel minden épeszűséggel) kezdetű alcímmel vezeti be. A furcsa viselkedések között a nem kódszerű sorok kezeléséről is ír, ami kommentek készítésére is jó, csak arra kell vigyázni, nehogy kód kerüljön bele. Azonban megjegyzi azt is, hogy ezzel a módszerrel nehéz felderíteni a hibákat.[12]
Jegyzetek
[szerkesztés]- ↑ The A-Z of Programming Languages: INTERCAL. Techworld, 2008. július 4. (Hozzáférés: 2012. március 10.)
- ↑ The INTERCAL Resources Page. Catb.org. (Hozzáférés: 2012. március 10.)
- ↑ a b c d e Clc-Intercal. Clc-Intercal, 2010. április 1. [2012. december 24-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. március 10.)
- ↑ a b c d e f g h i j k l m INTERCAL reference manual. [2011. július 16-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. március 10.)
- ↑ Princeton and Atari Syntax – C-INTERCAL 0.27 Revamped Instruction Manual. [2012. december 24-i dátummal az eredetiből archiválva]. (Hozzáférés: 2012. november 12.)
- ↑ a b c d e f g h C-INTERCAL supplemental reference manual. [2008. február 23-i dátummal az eredetiből archiválva].
- ↑ Stross, Charles. „Intercal -- the Language From Hell”, Computer Shopper (UK), 1992. szeptember 1.
- ↑ Broukhis, Leonid: BESM-6 Instruction Set. (Hozzáférés: 2008. április 15.)
- ↑ Backtracking in Intercal. Cse.unsw.edu.au, 2006. április 11. (Hozzáférés: 2012. március 10.)
- ↑ A COME FROM működése
- ↑ Threaded Intercal. Cse.unsw.edu.au, 2004. június 9. (Hozzáférés: 2012. március 10.)
- ↑ Mateas, Michael; Nick Montfort. „A Box, Darkly: Obfuscation, Weird Languages, and Code Aesthetics”. Proceedings of the 6th Digital Arts and Culture Conference, IT University of Copenhagen, 1–3 December 2005: 144–153.
Források
[szerkesztés]- Oliver Lau, Hexenwerk - Ein Plädoyer für esoterische Programmiersprachen, c’t 22/07, S. 192-199 sowie c’t extra 02/09, S. 40-45.