Egyes trollfajzatok, kik magukból penetráns, dögletes memetikai bűzölgést eregetnek állandóan mert másra nem képesek, és intellektuális csicskásaik, a
„mockosz kisz hobbitkák”, minden bizonnyal belekötnének szívesen a csodálatos mau nyelvbe, mondván hogy ez vajon „Turing-teljes-e”, tudom-e ezt BIZONYÍTANI?! Mert ha nem, akkor esetleg és netántán létezhetnek olyan feladatok, melyekre más programnyelvek alkalmasak, de az enyém nem... Nos, e helyütt leszámolunk e gonoszkodókkal!
Amit ugyanis a fenti bekezdés jelent, hogy a programnyelv alkalmas bármi olyan feladatra amit manapság egy programnyelvtől elvárnak, azt szaknyelven azzal a fogalommal fejezik ki, hogy a programnyelv úgynevezett „Turing-teljes”.
Ez a „Turing-teljes” fogalom természetesen megmagyarázható lenne ennél sokkal tudományosabban is, de ezt mellőzöm, mert e leírásban (is...) kerülöm a felesleges „felHOMÁLYosításokat”... Lényeg az, hogy ha valamely programnyelvre a nagyokosok azt mondják hogy ez „Turing-teljes”, akkor ezzel elismerték, hogy az a nyelv alkalmas mindarra, amire bármelyik eddig létrejött programnyelv, bár természetesen elképzelhető, hogy valami feladatot abban a nyelvben sokkal nehezebben lehet leprogramozni, mint egy másik nyelvben.
Azaz, bármire is legyen képes egy tetszőleges mai programnyelv, azt bármelyik másik programnyelv is képes megcsinálni, amennyiben az egy Turing-teljes programnyelv.
Hogyan is lehetne garantálni, hogy a mau nyelv teljes? Nos, a Turing-teljességnek van egy számunkra (azaz a mau nyelv minden igaz szívű és lánglelkű rajongója számára) módfelett előnyös szabálya, ami így hangzik:
Minden olyan programnyelv Turing-teljes, ami részhalmazként tartalmaz valamely másik Turing-teljes programnyelvet!
Ez különben logikus. Gondoljunk csak bele: Egy programnyelv lényegében utasítások egy halmaza. Ha van mondjuk 30 utasításunk, s azzal meg tudunk oldani bármely problémát, akkor ha ezen 30 utasításhoz hozzáveszünk még újabb mondjuk 47-et (vagy akármennyit), nyilvánvaló hogy akkor is meg tudjuk oldani az előző problémákat! Tudniillik ha olyan gondba ütközünk amik nem megoldhatóak az újabb utasításainkkal, akkor megoldjuk azokat legfeljebb a régi 30 utasításunk közül néhánnyal...
Nekünk tehát most nincs más dolgunk, mint hogy megvalósítsuk programnyel-vünkben valamelyik olyan már létező másik programnyelv utasításait, melyről
már korábban elismerték a „nagyokosok”, hogy az Turing-teljes. Ha ez sikerül nekünk, akkor teljesen mindegy, ezen felül mi mindent építünk még be a nyel-vünkbe: az egyszersmindenkorra Turing-teljesnek fog számítani, efelöl vita se lehet!
Nos, ezt megtettem. E nyelv amit „részhalmazként” beleépítettem a mau nyelvbe, a talán lehető legegyszerűbb Turing-teljes nyelv, az úgynevezett
„brainfuck” nyelv. Ténylegesen ez a neve, ami magyarul talán „agybaszónak”
fordítandó, már elnézést a csúnya szóért... És nem véletlenül ez a neve, ugyanis irtózatosan nehéz benne programokat írni! Ennek ellenére azonban Turing-teljes. És bár e nyelven egy programot megírni tényleg nehéz, de a programnyelv interpreterének a megalkotása nagyonis könnyű... Épp emiatt választottam!
A nyelv mindössze csak 8 utasítást tartalmaz ugyanis... A nyelvet Urban Müller készítette, azzal a céllal, hogy olyan Turing-nyelvet hozzon létre, amire a lehető legkisebb fordítóprogramot tudja megírni. A mau nyelv azonban ezt interpreter-ként valósítja meg, természetesen.
A brainfuck nyelvről itt található részletes Wikipédia-szócikk:
https://hu.wikipedia.org/wiki/Brainfuck
A Brainfuck nyelvnek egy univerzális byte-mutatója van, aminek a neve
„pointer”, és ami szabadon mozoghat az adatmemóriában, mely legalább 30000 byte nagyságú tömb illik hogy legyen, és amelynek alapértékei nullák. A pointer a tömb elején indul. Nem tudom, miért van ez a fétisizmus a brainfuck programozók körében, hogy a memóriatömb értéke éppen 30000 bájt nagyságú legyen - még ha legalább 32768 lenne a mérete, megérteném, mert az „kerek” szám kettes számrendszerben írva. De 30000?!
Na mindegy.
A nyelv nyolc parancsát egy-egy karakter reprezentálja:
> A pointer növelése eggyel
< A pointer csökkentése eggyel
+ A pointernél levő byte növelése eggyel - A pointernél levő byte csökkentése eggyel . A pointernél levő byte kiírása
, Byte bekérése és a pointernél tárolása
[ Ugrás a következő, megfelelő ] jel utánig, ha a pointer alatti byte nulla.
] Ugrás az előző, megfelelő [ jelig.
Ez igazán egyszerűnek tűnik.
A baj csak az, hogy e 8 utasítás 8 karaktere nagyonis olyan, amilyeneket máshol is használ a mau nyelv! De van megoldás. Van a mau nyelv kódjában
egy F nevű struktúra, mely mindenféle fontos adatokat tárol. Felvettem belé, e struktúrába a brainfuck flaget:
USC BRAINFUCKflag; // Ha 1: A "+ - > < . , [ ]" karaktereket brainfuck módban értelmezi, ha 0:
másképp.
E flag kezdetben 0 értékű, erre állítja be a konstruktorunk. (Azaz, a mau program indulásakor ez nulla). Kell tehát nekünk megfelelő utasítás e flag 1-re állításához (bekapcsolásához) és nullára állításához, azaz a kikapcsolására. E két utasítás a mau nyelvben a
/+
és a
/-utasítás. Természetesen a mau nyelv tartalmazza a megfelelő BRAINFUCK utasításokat is a fenti táblázat minden karakterére, de eszerint azokat csak akkor hajtja végre, ha a BRAINFUCK flaget bekapcsoltuk előbb a /+ utasítással.
Ezek után, ha efféle brainfuck progival találkozunk az Internet setét virtuális sikátoraiban, azt a következőképp adaptálhatjuk a mau nyelvünkhöz:
1. Kitörlünk belőle minden karaktert, ami nem a 8 brainfuck utasítás, azaz nem a .,<>+-[] karakterek valamelyike, vagy pedig megjegyzéssé fokozzuk le őket a // karakterpáros eléjük tevésével. (A sortörések, szóközök, tabulátorok maradhatnak).
2. Beszúrjuk az elejére:
[#c@0=30000]
Ez foglalja le a szükséges memóriaterületet, méghozzá a nullás sorszámú tömb unsigned char típusú értékeire. A 30000 helyett megadható más szám is, amennyi elég az aktuális brainfuck proginak, de a #c@0 nem lehet más, ez
„fixen behuzalozott” a brainfuck rutinokba. (Nem tartom e funkciót ugyanis olyan fontosnak, hogy azon görcsöljek, miként érhetek el e téren nagyobb rugalmasságot...).
3. Beszúrjuk az elejére:
/+
Ez kapcsolja be a brainfuck-értelmezést.
4. Szükség esetén, ha a program futása után a prompt rossz helyen jelenne meg, a legvégére szúrjunk be egy
/;
jelet, hogy kiírjon egy üres sort még.
Most már boldogok lehetünk, a nyelvünk részhalmazként tartalmazza a brainfuck nyelvet, ami Turing-teljes, TEHÁT ezek után a mi mau nyelvünk is Turing-teljes, efelől nem lehet vita, s ez azt jelenti, hogy minden szaktekintély által elismerten alkalmas a nyelvünk BÁRMI feladat megoldására, ami bármi más programnyelvvel is megoldható egyáltalán!
Példákat BRAINFUCK progikra nem közlök itt e leírásban, de a mau forráskód mellé becsomagolok párat. Azokat azonban nem én írtam, hanem máshonnan vadászgattam őket össze az Internetről, csak a fenti leírás szerint „adaptáltam”
őket a mau nyelvhez. Akinek tehát van mau interpretere, az ezentúl nem kell kétségbeessen, ha talál valami efféle titokzatos stringet egy aláírásban:
++++[>+++++<-]>[<+++++>-]+<+[>[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]
+>>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----
<-]<]<<[>>>>>[>>>[-]+++++++++<[>-<-]+++++COMMENT+COMMENT+++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<-]
Ezt a hup.hu portálról vadásztam le, e link alól:
http://hup.hu/node/116498
Ebből ez lett a „mau-képessé” átalakítás után:
#!mau
[#c@0=30000]
/+
++++[>+++++<-]>[<+++++>-]+<+[>[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+>>>+[[-]+++++
+>>>]
<<<[[<++++++++<++>>-]+<.<[>----<-]<]<<[>>>>>[>>>[-]+++++++++<[>-<-]
+++++
// COMMENT +
// COMMENT
+++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<-]
/;
Amint látom, a 0-10000 tartományba eső négyzetszámokat írja ki.