INTERCAL (programozási nyelv)

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.

Jimbo Lyon, az INTERCAL egyik szerzője

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

 
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 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ó:

INTERCAL operators[3][4][6]
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

  1. The A-Z of Programming Languages: INTERCAL. Techworld, 2008. július 4. (Hozzáférés: 2012. március 10.)
  2. The INTERCAL Resources Page. Catb.org. (Hozzáférés: 2012. március 10.)
  3. 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.)
  4. 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.)
  5. 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.)
  6. 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].
  7. Stross, Charles. „Intercal -- the Language From Hell”, Computer Shopper (UK), 1992. szeptember 1. 
  8. Broukhis, Leonid: BESM-6 Instruction Set. (Hozzáférés: 2008. április 15.)
  9. Backtracking in Intercal. Cse.unsw.edu.au, 2006. április 11. (Hozzáférés: 2012. március 10.)
  10. A COME FROM működése
  11. Threaded Intercal. Cse.unsw.edu.au, 2004. június 9. (Hozzáférés: 2012. március 10.)
  12. 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.

Külső linkek szerkesztés

A Wikimédia Commons tartalmaz INTERCAL (programozási nyelv) témájú médiaállományokat.