• Nem Talált Eredményt

fejezet - A mau nyelv változói

Aki egy mau nyelvű programra ránéz, első pillanatban valószínűleg elszörnyed, mert teljesen érthetetlennek tűnik számára a sok krixkrax. Leginkább még talán a Perl nyelvre emlékeztet, de annál is rosszabb. E benyomás túlnyomórészt azonban csak egyetlenegy dologból fakad: abból, hogy a mau nyelv a változókat tényleg meglehetősen egzotikus módon kezeli/nevezi, különben annak érdekében, hogy a kód végrehajtása minél gyorsabban történhessen. Hogy a sebességnek és a változók nevének mi köze van egymáshoz, azt azonban itt nem részletezem, akit érdekel olvassa el a Bevezetésben említett tanulmányt mely e nyelv megalkotásának folyamatáról szól. Mindenesetre semmiképp se lehet vitás, hogy a mau nyelv messze a legnagyobb nehézségét a megértésben és elsajátításában a változókezelés megtanulása jelenti. Aki ezt „túléli”, annak a többi már könnyű. A mau nyelvnek ugyanis számos előnye van, például nem kell benne mutatókkal bűvészkedni már egy nyamvadt stringkezelés kedvéért is, mint a C nyelvben (mely különben kedvenc programnyelvem, a mau nyelv interpretere is C/C++

nyelven van megírva). A mau nyelv ugyanis számos beépített magas szintű adattípussal rendelkezik, nemcsak stringekkel, de stringtömbökkel, vermekkel, sőt még külön „directory” adattípusa is van! E nyelv tehát valójában nagyon könnyű, mondhatnám hogy egyenesen KÉNYELMES. Kivéve a változók nevét, igen, sajnos, gomen nasay, sorry és excuse me...

Ami tehát a változókat illeti: Minden mau program (pontosabban egy mau program minden külön NÉVTERE...) pontosan 256 különböző nevű változóval rendelkezhet, semmi esetre sem többel, egyáltalán soha és semmikor, tényleg, kivéve amikor mégis. (hehehe...) E változók azonban nem egy konkrét szám-értéket jelölnek, hanem az hogy pontosan miféle érték is tartozik hozzájuk, az attól függ, milyen kontextusban hívják meg őket. Például minden rendszerfüggvény meghatározott típusú input paraméter(eke)t vár el, ezért a megfelelő típusú adatot olvassa ki a változóból. Természetesen létezik casting operátor is, amivel ezt befolyásolni tudjuk.

A fentiek megértéséhez szükséges észben tartani, hogy tehát egy változó, mondjuk az amit a @A karakterpárossal jelölünk (minden változó neve okvetlenül a @ jellel kezdődik, mindig, kivéve amikor mégsem...) tulajdonképpen egy 16 bájt méretű memóriatartományt címez meg, amely unionként van felosztva. Ezen union struktúrája a következő:

union V { // Az univerzális változó

unsigned char c[16]; // Mérete 1 bájt signed char C[16]; // Mérete 1 bájt unsigned short int i[ 8]; // Mérete 2 bájt

signed short int I[ 8]; // Mérete 2 bájt

// A V unionban elhelyezkedő mezők egymáshoz viszonyított pozíciói:

// | c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | c[8] | c[9] | c[10] | c[11] | c[12] | c[13] törődnie a mau nyelven programozónak, ezt csak pár rendszerrutin használja

„ott lenn a mélyben”, csak a teljesség kedvéért van itt feltüntetve.

Amikor tehát az interpreter egy aritmetikai kifejezés kiértékelése közben belefut mondjuk egy @A nevű változóba, akkor az hogy ennek hatására miféle értéket szolgáltat nekünk, attól függ, épp milyen TÍPUSÚ adatot óhajt előcsalogatni magának. Ha az mondjuk unsigned char típusú, akkor az A változó unionjának c[0] rekeszében található értéket olvassa ki. Ha azonban neki mondjuk egy unsigned int érték kell, akkor NEM azt csinálja hogy a c[0]

rekeszben levő, az előbb említett egybájtos értéket castolja 4 bájtos unsigned int értékké, hanem az l[0] rekeszben található mind a 4 bájtot kiolvassa, s ezt adja vissza mint egy unsigned int értéket!

A mau nyelvben kivétel nélkül minden függvény és utasítás esetén a legisleg-szigorúbban meg van határozva, hogy miféle típusú adatot vár a megfelelő helyen, pozícióban. Az if után például unsigned char érték kell jöjjön. (A részleteket lásd majd az if-ről szóló fejezetben). Ez nem jelenti azt, hogy más típusú adat nem adható meg azon a helyen, amennyiben azonban azon adat alapértelmezett típusa nem az amit azon a helyen az interpreter elvárna, külön ki kell tennünk a „casting operátor” jelét, ami jelzi az interpreternek, hogy most épp miféle adatot is akarunk vele „megkajáltatni”. Azaz, a @A egy egész csomó mindenfélét jelenthet, attól függően, hogy épp miféle környezetben áll.

Ez egy „nem egyértelmű” neve a változónak, mert csak azt határozza meg, épp melyik 16 bájtos unionról van szó, de azt nem, hogy annak melyik mezőjéről. Ezt a jelölésmódot nevezzük majd e könyvben úgy a továbbiakban, hogy a változó „rövid neve”.

Természetesen van mód a változó teljesen konkrét meghatározására is, ez történik a már sokszor emlegetett „casting operátorral”. Egy efféle meghatározás, amit a továbbiakban a változó „teljes nevének” nevezünk, így néz ki:

#c@A

A "c" karakter helyén állhatnak más karakterek is, amik a típusra utalnak. A lényeg az, hogy e karakter közvetlenül a # jel után kell álljon, nem lehet köztük whitespace. A típusjelölő karakter (e példában a „c”) és a @ jel közt azonban már állhat akárhány whitespace karakter is. Általában, a mau nyelvben ahol állhat 1 whitespace karakter, ott állhat akármennyi is.

A mau nyelv a 33-nál kisebb ASCII kódú karaktereket tekinti whitespace-nak.

Ezek közül az ismertebbek:

0

9 (=TAB)

10 (=újsor karakter) 11

12 13

32 (=SPACE)

A mau nyelvben a # karakter (tehát a casting operátor) után a következő karakterek állhatnak, e jelentéssel (ezek ugyanazok, vegyük észre, mint a fenti unionban):

c: unsigned char C: signed char

i: unsigned short int I: signed short int l: unsigned int L: signed int

g: unsigned long long G: signed long long f: float

d: double

D: long double s: string

Vegyük észre, hogy a nem lebegőpontos típusok esetén az előjeles (signed) típusokat jelölő karakterek az előjel nélküliek nagybetűs párjai, így ez könnyebben megjegyezhető!

Akadnak a fentieken kívül még egyéb típusok is, de azok csak speciális esetekben használhatók, ilyenek az inputfile, outputfile, directory, veremtár, benchmark... ezekről később lesz szó. Bár igazából a stringtípus is olyasmi, aminek ezen unionhoz nincs köze, de mégis jó dolog megemlíteni itt, mert az azért mégis majdnem bárhol használható, ahol a numerikus változók (legalábbis közülük a nem lebegőpontosak).

Megjegyzendő továbbá, hogy immár 2 stringfajta is létezik a mau nyelvben: az egyik a „szokásos”, a másik egy speciális, amit JELSOR-nak nevezek a megkülönböztetés végett, s ez nem bájtokból áll, hanem BETŰKből... E disztinkció oka, hogy ez utóbbi 2 micsoda (a BETŰ és a JELSOR) teljesen az UTF-8 támogatására van „kihegyezve”. Ezek casting operátorai:

A BETŰé: #u A JELSORé: #U

Azért kis és nagy „u”, mert ugye UTF-8 kódolású... Ezekről soká-soká nem fogsz e doksiban többet olvasni, legfeljebb elvétve pár szót, hanem egy sokkal későbbi fejezet teljes egészében ezekről szól majd!

Amennyiben tehát azt írjuk hogy #c@A, az az A változó unionjának c[0]

rekeszét jelöli mint unsigned char szám. A #l@A pedig az A változó l[0]

rekeszét jelenti, ami 4 bájt, s unsigned int értékként értelmeztetik.

Amennyiben mi kifejezetten épp az A változó c[0] rekeszének 1 bájtnyi értékét akarjuk megkapni, de igenis unsigned int számként és nem unsigned char értékként, akkor azt kettős castolással tudathatjuk az interpreterrel:

#l#c@A

Lehetne nemcsak kettős, hanem hármas, négyes, akárhányas castolást is alkal-mazni, azaz akárhány casting operátort egymás után írni. Ugyanis nagyon fontos megjegyezni, hogy a casting operátor nem olyasmi, ami speciálisan csak egy változóra vonatkozik, hanem A TELJES, ŐUTÁNA KÖVETKEZŐ ARITMETIKAI KIFEJEZÉSRE! Az hogy egy változóból miféle adatot szed elő az interpreter, attól függ, épp azon a helyen mit vár el alapértelmezettként; - kivéve ha van valami casting operátor közvetlenül a változó előtt. Ha ugyanis van, akkor az annak megfelelő adatot szedi elő az unionból. Ha van ettől balra másik casting operátor is, akkor a már előszedett adatot arra castolja. Ha még másik is van, akkor megint castol, és így tovább. Ha már nincs több, akkor legvégül arra castol, ami típus neki kell az adott művelethez, s elvégzi az így kapott adattal azt, ami ott a dolga.

Amennyiben nem tudod biztosan, hogy egy rövid névvel jelzett változót azon a helyen a programban épp miféle típusként akarna kezelni az interpreter, akkor nem kell elkeseredned, egyszerűen tedd ki elé a konkrét casting operátort, ami neked ott épp megfelelő, és kész! Semmi baj nem történik ugyanis, ha a casting operátor olyan helyen szerepel, ahol tulajdonképpen feleslegesen van ott. Ez mindössze 2 plusz bájt a programkódban, s esetenként egy plusz függvényhívás. Nemigen jelent érzékelhető mértékű programlassulást általában, hacsak nem egy 10 milliószor lefutó ciklus belsejében van.

A fenti jelöléstípus azonban csak az union nullás indexű mezőit tudja visszaadni. Ha olyan mező kell aminek az indexe nem nulla, azt a következőképp adhatjuk meg:

@A:3

Természetesen a „3” szám helyén nemcsak a 3-as szám állhat. Hogy mennyi, az attól függ, az adott típusú adatból mennyi fér el a 16 bájtos unionban.

Korábban megadtam az union felépítésének ábráját, abból láthatóak a maximális indexek. Ez az unsigned és signed char típusnál lehet a legnagyobb,

tudniillik 15. A long double értéknél azonban semmilyen se lehet, mert az egymaga 16 bájt hosszú.

Most már gondolom érthető, miért viccelődtem korábban azzal, hogy a mau nyelvben csak 256 különböző változó lehet, és semmiképp sem több, kivéve amikor mégis... E 256-os maximális érték ugyanis csak az unionokra vonatkozik. A long double típust kivéve azonban a többi adattípusból több is belefér egy 16 bájt hosszú unionba, azaz simán megcsinálhatjuk, hogy mondjuk a @A nekünk egyszerre több változót is jelentsen:

#f@A:0 // ez egy float szám, 4 bájt a sizeof mérete

#i@A:2 // unsigned short int, 2 bájtos sizeof mérettel

#C@A:6 // signed char, 1 bájtos sizeof mérettel

#C@A:7 // signed char, 1 bájtos sizeof mérettel

#g@A:1 // unsigned long long, 8 bájtos mérettel.

A fentiek mind a @A változóban vannak, egyidejűleg, és „nem bántják egymást”. Azaz, végeredményben 256-nál jócskán több változónk lehet, egyedül akkor van éppen pontosan csak 256 változónk, ha kizárólag long double változókat használunk. De olyan eset alig is képzelhető el. Ráadásul majd e leírás későbbi részeiben láthatjuk, hogy akad még ezeken felül is sok további lehetőségünk mindenféle változókat használni az itt most bemutatottakon túl is, tudniillik veremtárakban, vagy tömbökben, vagy álfüggvények névterében levő változókkal bűvészkedni, vagy azokat használni amiket a függvényünk az őt hívó programból ad át, vagy a szülőnévtér változóit használni... s akkor még nem is beszéltünk arról, hogy egy függvényen belül akárhány elkülönített névteret is létrehozhatunk, ráadásul e névtereket tetszőleges mélységben egymásba skatulyázva... Szóval nem kell aggódnia annak, aki netán úgy véli, a 256 lehetőség a változók nevére túl kevés! Bár megjegyzem, én úgy találtam hogy többnyire nemhogy 256 elegen-dő, de az is amit kizárólag az angol ABC kis- és nagybetűivel tudok megvalósítani. Ha több változó kell egy függvényen belül, úgyis tömböket használok.

Továbbá, a fenti példák amiket felsoroltam, hányféleképp használhatjuk egyide-jűleg a @A nevet változóazonosításra, amiatt se teljesek, mert például a stringet jelölő #s@A változónak semmi köze sincs ezen unionhoz, az tehát egy további plusz lehetőség!

Na most, fontos tudni, hogy a mau programok azért tűnnek bonyolultnak, mert a

@A:3 jelölésben az „A” és a „3” helyén is állhat tetszőleges (alapértelmezésként unsigned char típusú) aritmetikai kifejezés... Tehát más változók is, sőt, akármi-féle tetszőlegesen bonyolult kutyulmány! Muszáj is hogy ez így legyen, mert változóból (azaz inkább változó-unionból) 256 fajta lehetséges (egy névtéren belül), s ennyit nem lehet megnevezni mindössze az angol ABC kis- és nagybetűivel.

Az aritmetikai kifejezések a mau nyelvben mindazonáltal nem különösebben bonyolultak. (A változónevektől eltekintve. Bár tulajdonképpen azok is csak akkor bonyolultak, ha nagyon egymásbaskatulyázzuk őket).

Ami a konstansokat illeti, azokra a következő szabályok érvényesek:

—Minden számsorozat ami a 0-9 karakterek valamelyikével kezdődik, DECI-MÁLIS SZÁMKÉNT van értelmezve. (Igen, a nullával kezdődőek is, azok sem oktálisnak hanem decimálisnak vannak tekintve!)

—A $ jellel kezdődnek a hexadecimális, azaz a 16-os számrendszer beli számok. Ezek nem lehetnek lebegőpontosak. A 9-nél nagyobb értékű számjegyek megadhatóak kis- és nagybetűkkel is, azaz az a-f és A-F betűkkel egyaránt.

—A % jellel kezdődnek a bináris számok. Ezek is csak egész típusúak lehetnek.

—Amennyiben az interpreter egy „o” vagy „O” betűbe szalad bele, megnézi, ezt valamely oktális számjegy követi-e, vagyis a 0-7 számjegyek valamelyike.

Ha igen, akkor beolvassa azt a számsorozatot oktálisan, s ez lesz az adott konstans értéke. Ha nem követi a kis vagy nagy o betűt oktális számjegy, akkor viszont a betű (vagyis az „o” vagy „O” karakter) ASCII kódját adja vissza.

—Tetszőleges nem whitespace karakter esetén, ha az nem „$”, „%”, „#”, „?”,

„o”, „O” vagy „'” azaz aposztróf jel, nem is unáris operátor vagy netán más olyasmi ami valamely speciális jelentéssel bír a mau programnyelvben (ezt azért írom ilyen óvatosan, mert ugye lehet ám hogy a nyelv bővülni fog...) ekkor tehát az adott karakter ASCII kódját adja vissza. Az angol ABC kis- és nagybetűit illetően egészen biztos hogy ez a helyzet, s ez meg is marad, kivéve az „o” és „O” betűket, ahol ez attól is függ, követi-e őket oktális számjegy, ezt fentebb már írtam.

—Az aposztróf jel esetén („'”) az aposztrófot követő bájt ASCII kódját adja vissza, akármi legyen is az, akkor is ha az valamely whitespace karakter, vagy nem kiiratható karakter.

Egy konstans addig olvastatik be, azaz a karaktereket addig tekinti az interpreter a konstans részének, ameddig olyant nem talál, mely nem esik bele az adott számrendszer értelmezési tartományába.

Ennek megfelelően az alábbi jelölések mind ugyanazt a változót határozzák meg:

@A

@'A

@65

@$41

@%1000001

@o101

@O101

Nyilvánvaló természetesen, hogy e jelölésmódok közül a @A típusú a leggyorsabban feldolgozható, leghatékonyabb, sőt, a legkönnyebben olvasható is.

A mau nyelvnél SZABVÁNY, azaz alapvető előírás, hogy minden létrejövő névtér esetén a névtér LÉTREJÖTTEKOR azonnal rendelkezésre áll minden fentebb felsorolt változótípusból mind a 256 darab, azaz nem kell őket semmiféle módon előre deklarálni, meghatározni, előírni, definiálni, stb, másrészt kivétel nélkül mindegyiknek a kezdeti értéke éppen pontosan 0 azaz NULLA és nem más! Amennyiben valamikor valamely mau változat (release) esetén ez nem

így volna, az igenis nem feature, hanem ordas nagy BUG, méghozzá EXTRÉM KRITIKUS minősítéssel!

Figyelem! A névtér LÉTREJÖTTEKOR lesz nulla a változók értéke, nem amikor a névtérbe belelépünk, tudniillik függvényeknél a változók utoljára használt értéke megmarad a következő belépés számára!