Hlavní navigace

Intercal: Dostatečně šílený programovací jazyk

1. 4. 2005
Doba čtení: 6 minut

Sdílet

Jste znuděni "běžnými" programovacími jazyky? (Oops...tohle už zní jako běžný prací prostředek...) Chtěli byste vyzkoušet něco úplně jiného? Potom vám představím programovací jazyk, který si dal za cíl se co nejvíce lišit od "normálních" jazyků.

Při jeho studiu jsem si vzpomněl na citát z knihy Richarda Feynmana: „vaše [fyzikální] teorie není dostatečně šílená na to, aby byla pravdivá“. INTERCAL naopak JE dostatečně šílený na spoustu věcí: Na aprílový žert. Na odreagování při programování. Na navození pocitu absurdity. Na získání či ztrátu nadhledu. Na cokoliv.

Celé jméno programátorského díla, o kterém budu psát, je „Compiler Language With No Pronounceable Acronym“, což se logicky zkracuje na INTERCAL. Autory jsou Donald R. Woods a James M. Lion z Princetonské univerzity, produkt spatřil světlo světa 26. května 1972. O osmnáct let později vznikl UNIXový port zvaný C-INTERCAL od Erica S. Raymonda.

Jedinou konstrukcí, která funguje v podstatě stejně jako v obvyklých programovacích jazycích, je přiřazovací příkaz. Všechny ostatní jsou více či méně divné. V manuálu je „síla INTERCALu“ demonstrována tím, že ukázkový program (který navíc provádí cosi naprosto neužitečného) má 22 příkazů a byl napsán za 15 až 30 minut, zatímco ten samý program ve SNOBOLu či APL byl na pár řádků a byl napsán během minuty. Podobnými absurdními tvrzeními je manuál prošpikován, což znamená, že se dobře čte. Budu se snažit, aby se podobně dobře četlo i moje povídání. Například ještě upozorním, že autoři manuálu používají lehce nestandardní pojmenování speciálních znaků na klávesnici, které jsem si dovolil podobně nestandardně pojmenovat v češtině.

Takže dosti úvodu a jdeme na popis jazyka:

Proměnné se neoznačují jménem, ale celým číslem od 1 do 65535 – existují dva typy proměnných, šestnáctibitové integery (označují se beďarem „.“ před jejich jménem-číslem) a 32bitové integery (označené dvojbeďarem „:“). Například tedy .23 je 16bitová proměnná a :23 je (od ní naprosto, naprosto různá) 32bitová. Oba typy proměnných jsou bezznaménkové (unsigned).

Konstanty jsou čísla od 0 do 65535, prefixují se vězením („#“).

Další entitou označenou číslem s prefixem je pole: šestnáctibitové pole se označuje ocáskem „,“ (tedy např ,234) a 32bitové hybridem „;“ (např. ;322) – v obou případech za číslem následuje slovo SUB následované indexem. Indexy mohou obsahovat libovolné výrazy.

Takže .23 ,23 :23 ;23 #23 jsou pět různých věcí (objektů, entit, prvků jazyka…jak chcete).

Nyní vám představím operátory…byly zvoleny opravdu použitelné a přehledné, posuďte sami. (Autoři jazyka tvrdí: „buďte prosím laskaví na naše operátory: nejsou příliš inteligentní, ale jsou všechno, co máme…“)

Binární operátory jsou dva: prolni (interleave) označovaný znakem „velký prachy“ („$“) a vyber (select) označený znakem „sinusoida“ („~“).

Operátor prolnutí bere dva 16bitové operandy a vytvoří 32bitový výsledek vzniklý pravidelným střídáním bitů operandů – tedy například #65535$#0 je 101010…10 čili 2863311530, zatímco #0$#65535 je 0101…01 čili 1431655765 . Jasné?

Operátor výběru vezme z prvního operandu ty bity, které jsou ve druhém operandu nastavené na 1 a zarovná je ve výsledku doprava, zleva doplní nulami. Například #179~#201 dává 9, zatímco #201~#179 dává 17. Bezva.

Unární operátory jsou taky takto bezvadně použitelné, možná ještě víc: klikyhák („&“) – logické AND, véčko („V“) – logické OR a cože („?“) logické XOR. Operátory se aplikují vždy na dvojici vedle-sebe-ležících bitů, výsledek z prvního a posledního bitu jde do prvního bitu. Operátor se zapisuje mezi beďar, ocásek, hybrid, vězení či podobné znaky a číslo proměnné. Například: #&77 je 4, #V77 je 32879 a #?77 je 32875. Snadné, že?

Priority operátorů nejsou vtipně žádné, takže se musí uzávorkovávat pomocí jisker ' či zaječích uší " .

Příkládek z manuálu: ‚#165$#203‘~#358 je 15, #165$‚#203~#358‘ je 34915, avšak #165$#203~#358 je syntaktická chyba kvůli nejednoznačnosti.

Příkazy nejsou o nic méně cvoklé než výrazy. Obecná struktura může obsahovat

  • nepovinné číselné návěští zapsané mezi couvající měsíček „(“ a dorůstající měsíček „)“
  • povinně DO, PLEASE nebo PLEASE DO
  • nepovinně číslo od 0 do 100, před kterým je kulička-lomeno-kulička („%“) – označuje procentuální pravděpodobnost, že bude příkaz proveden
  • dále vlastní příkaz: těch je celkem třináct, viz dále

Jediným „normálním“ příkazem je příkaz přiřazení, jak jsem již říkal. Tvoří ho zpětný zobáček („<“) následovaný červíkem („-“). Například inverze nejnižšího bitu prvního prvku dvourozměrného pole číslo 1 se realizuje takto:

PLEASE DO ,1SUB#1#1 <- '?,1SUB#1#1$#1'~'#0$#65535'

Další příkazy:

(návěští) NEXT

skočí na návěští a uloží návratovou adresu do zásobníku. Tento zásobníček má maximálně 79 položek, pokus uložit další vede ke geniální chybové hlášce

PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON
FORGET výraz

vyhodnotí výraz a vymaže tolik položek z NEXTového zásobníku, kolik je hodnota výrazu. Takže

DO (111) NEXT
...
(111) PLEASE FORGET #1

je v podstatě nepodmíněný skok.

RESUME výraz
taky vezme položky ze zásobníku, ale na poslední z nich skočí (návrat z „podprogramu“)
STASH seznam proměnných

uloží si hodnoty těchto proměnných bokem. Takto uložené hodnoty se potom zpátky nahrají příkazem RETRIEVE seznam proměnných. Proměnné se v seznamu oddělují symbolem první pomoci („+“), např.:

PLEASE STASH .123+:123+,123
IGNORE seznam proměnných
systém bude ignorovat (neprovádět) změny na proměnných v seznamu
REMEMBER seznam proměnných
proměnné zase „odignoruje“ čili zruší efekt IGNORE

Podobně jako IGNORE a REMEMBER pracují s proměnnými, pracují ABSTAIN a REINSTATE s příkazy.ABSTAIN FROM (návěští) způsobí, že se příkaz na daném návěští nebude provádět. DO ABSTAIN FROM STASHING vypne fungování všech příkazů STASH, PLEASE DO ABSTAIN FROM CALCULATING vypne přiřazovací příkaz. Opět můžeme pomocí symbolu první pomoci („+“) vytvářet seznam:

PLEASE ABSTAIN FROM NEXTING+FORGETTING

Příkaz REINSTATE znovu obnoví funkci ABSTAINovaných příkazů, např.

DO REINSTATE STASHING+CALCULATING

Z toho vyplývá malá zrada: příkaz DO ABSTAIN FROM REINSTATING není příliš doporučován…

Dále tu máme v jistém smyslu opak příkazu GO TO – příkaz COME FROM: spuštění

PLEASE COME FROM (návěští)
způsobí, že pokud někdy poté bude spuštěn příkaz na (návěští), hned potom nám to skočí na příkaz následující po COME FROM.

Vstup a výstup je v INTERCALu řešen také pěkně divoce:

WRITE IN seznam
realizuje vstup do proměnných ze seznamu, vstupní hodnoty uživatel vypisuje po číslicích slovy, například pokud spustíme program a chce po nás vstup, 182 do něj vepíšeme jako ONE EIGHT TWO. Super, ne?

Analogicky

READ OUT seznam
vypíše proměnné v seznamu, ale to by nebyl INTERCAL, aby je vypsal normálně. Vypisuje se -tramtadadá- římskými číslicemi. Přesněji řečeno jsou to „extended“ římské číslice: používají se například i malá písmena, která znamenají „krát milion“, nadtržítko (čili podtržítko na předchozím řádku) znamená „krát tisíc“. Nula se vypíše jako samotné nadtržítko.

To by bylo ke vstupu a výstupu vše.

A naposledy nám tu zbyl – na poměry INTERCALu relativně zvláštní, protože podobně jako příkaz přiřazení zvláštní není – příkaz GIVE UP, který ukončí program.

Ještě je tu další pěkná vlastnůstka: jak jste si všimli, příkazy vždy začínají DO, PLEASE nebo PLEASE DO. Můžete použít libovolný z těchto tvarů uvození příkazů, ovšem pozor: pokud obsahuje PLEASE méně než jedna pětina příkazů, program se nezkompiluje, protože není dostatečně zdvořilý. Naproti tomu pokud je více než jedna třetina PLEASE, program je příliš zdvořilý a opět se nezkompiluje. Dokonce existuje EMACSový mód intercal.el, který pomáhá vyrovnat se s touto velmi user-friendly vlastností.

root_podpora

Tak to by bylo asi vše – na závěr uvedu vysoce použitelný příklad z manuálu, který vezme 32bitová neznaménková čísla, interpretuje je jako znaménková, udělá dvojkový komplement a vytiskne jejich absolutní hodnotu. Program skončí při zadání nuly.

DO (5) NEXT
    (5) DO FORGET #1
        PLEASE WRITE IN :1
        DO .1 <- '?":1~'#32768$#0'"$#1'~#3
        DO (1) NEXT
        DO :1 <- "'?":1~'#65535$#0'"$#65535'
                ~'#0$#65535'"$"'?":1~'#0$#65535'"
                $#65535'~'#0$#65535'"
        DO :2 <- #1
        PLEASE DO (4) NEXT
    (4) DO FORGET #1
        DO .1 <- "?':1~:2'$#1"~#3
        DO :1 <- "'?":1~'#65535$#0'"$":2~'#65535
                $#0'"'~'#0$#65535'"$"'?":1~'#0
                $#65535'"$":2~'#0$#65535'"'~'#0$#65535'"
        DO (1) NEXT
        DO :2 <- ":2~'#0$#65535'"
                $"'":2~'#65535$#0'"$#0'~'#32767$#1'"
        DO (4) NEXT
    (2) DO RESUME .1
    (1) PLEASE DO (2) NEXT
        PLEASE FORGET #1
        DO READ OUT :1
        PLEASE DO .1 <- '?"':1~:1'~#1"$#1'~#3
        DO (3) NEXT
        PLEASE DO (5) NEXT
    (3) DO (2) NEXT
        PLEASE GIVE UP

Přeji vám příjemnou zábavu s tímto nevšedním programovacím jazykem.

Byl pro vás článek přínosný?

Autor článku