Az RPG programozási nyelv

Típusok, típuskonstrukciók



Indikátorok

Bevezetés

Ehhez kell egy kis bevezető az RPG egyik fontos típusárol, az indikátorról. Az indikátorok logikai változók, 0 ill. 1 értéket vehetnek fel, amelynek akár explicit módon is adhatunk értéket, akár egy utasítás után írhatjuk, hogy az állítsa be futásának megfelelően az értéket. (Tehát értéke állítható értékadó utasítással, vagy más utasítás kódolt mellékhatásaként is változhat.) Ezen kívül indikátor vagy negáltja ill. indikátorokból képezett logikai kifejezések szerepelhetnek egy utasítás előtt, ekkor az utasítás a kifejezés kiértékelése után fut le, annak igaz értéke mellett. A módszer alkalmazható speciális rekordleíró fájlok pl. display file-ok, printer file-ok, menü file-ok esetén is, ekkor például egy mező csak az előtte álló indikátor igaz értéke mellett jelenik meg a képernyőn, esetleg a megjelenités attributumai (szin, vilagossag) függhetnek indikátoroktól. Indikátorokkal figyelhetjük a különböző kontrollfokozatokat, a lapváltást, valamint a kártyák ellenőrzését is lehetővé teszik. Az AS/400 RPG-ben fő szerepük az input/output folyamatok vezérlésénél van, korábbi RPG verziókban az indikátorok értékétől függő utasítás végrehajtás volt az egyetlen lehetőség a programelágazásokra. Alapjában véve három féle indikátort különböztetünk meg: "belső indikátor"=>Nem a felhasználó feladata a bekapcsolása, "felhasználói indikátort"=>Tetszés szerint állítható az értéke (SETON, SETOF, MOVE), egy utasítás végrehajtása során a létrejött eredménytől függően lehet kapcsolni, "külső indikátor"=>A felhasználó tudja be- és kikapcsolni, de nem csak programutasításokon keresztül, hanem kívülről is, a program indítása előtt.

Részletek

Mivel az indikátorok igazi unikumnak számítanak a programozási nyelvek által kínált eszközök közt, érdemes őket részletesebben is megvizsgálni. A különféle specifikációkon megadható indikátorokat a következőképpen lehet csoportosítani:

A nem specifikációkban megadható indikátorok közül megkülönböztetünk külső és belső indikátorokat. A külső indikátorok eredményüket kívülről (CL parancsokból, vagy egy másik RPG programból) kapják, míg a belső indikátorok (1P, LR, MR, RT) az RPG programciklus során kapnak értéket.

A halt indikátorokkal (H1-H9) hibákat jelezhetünk. Ekkor a user egy üzenetet kap, amire három választ adhat:

Táblázatok, Tömbök

Táblázatok

Kétféle táblázat kezelését támogatja a nyelv. Az egyszeres (single) és a kétszeres (alternate). A táblázatra jellemző, hogy azonos típusú és egyenlő hosszúságú elemek véges számú sorozata. Az elemeket azok sorszámával azonosítjuk. A kétszeres esetben az elhelyezés váltakozva történik, az azonos sorszámú elemek elhelyezése váltakozva megy végbe. A két táblázat elemeinek hossza eltérhet egymástól. A táblázatos file definícióját a file-leírás kiegészítésére szolgáló E-űrlapon kell megadni.

Tömbök

A tömbök felépítése nagyon hasonló a táblázatokhoz. Lehetőség van egyszeres és kétszeres tömbök alkalmazására. Pl.

XFOOT TMB SUM

A numerikus elemeket tartalmazó TMB tömb elemeit összegzi, és az eredményt SUM-ban adja vissza. Hivatkozás a tömb egyes elemeire: tömbnév, index Az index megadható konstanssal, vagy egy egész értéket tartalmazó mező azonosítójával.

Egyéb típusok

Pointer típus (természetesen) nincs, meglehetősen erősen védett a rendszer a közvetlen memóriahozzáféréstől, de az elterjedt programozói stílus és nem utolsó sorban a megoldandó feladatok nem is teszik szükségessé használatát.

Érdekesebb típusok: többszörös előfordulású adatszerkezet, gyakorlatilag tömbhöz hasonló, amely adott adatszerkezetet tárol. A tömbök inicializálásának módja szerint három típus különböztetünk meg: futás közben értéket kapó tömbök, fordítási időben inicializált tömbök, és a programinicializáláskor töltött tömbök. Van tömb típus is, amely annyiban érdekes, hogy feltöltése történhet fájlból, például olyan módon is akár, hogy megadok egy adatfájlt, megadom azt, hogy a tömböm hány elemet és milyen hosszú elemet tartalmaz, és azt, hogy a fájl egy rekordja a tömb hány elemét tartalmazza. Ezután az RPG ún. pre-run időben feltölti értékekkel a tömbelemeket. Tömbben csak egyszerű adattípusok tárolhatóak. Érdemes még szólni az adatelemek attribútumairól, mivel az RPG-ben nagy jelentősége van ezek specifikálásának. Az attribútumok vonatkozhatnak file-ra, rekordszerkezetre vagy mezőre. Definiálhatnak unique tulajdonságot (rekordra), referenciát (rekordra, mezőre), ekkor a mező leírása nem helyben, hanem a referált fájlban található. Előnyös lehet a használata, hiszen elég egy fájlt változtatni ahhoz, hogy a hatása minden hozzá kapcsolódó fájlban észlelhető legyen. Attribútum vonatkozhat még megjelenítési módra, kommunikációs kapcsoltatokra és még sok egyébre. Az RPG utasításban hivatkozhatunk az egész tömbre, illetve annak egy konkrét elemére. Amennyiben az egész tömbre hivatkozunk, akkor az utasításban csak a tömb neve szerepel, míg amikor egy konkrét elemére, akkor tömbnév, index szerepel. A "tömbnév, index" karaktersorozatmaximum 6 hosszú lehet. Minden tömböt deklarálni kell az E kártyán, meg kell adni a tömb nevét, elemszámát, hosszát és a decimális jegyek számát (természetesen csak numerikus adatok esetén).

Beépített adattípusok

Ezekről már nagyrészt szóltam a Változók témakörnél. Típusok csak arra kellenek, hogy a tárolási módot megadja.

Érdekesség az, hogy egy rekordszerkezet mezőire több változót is deklarálhatok, így például lehetőség van arra, hogy egy dátumot egyben (nap/hónap/év) és külön is kezeljek.

Változók, konstansok

Az RPG programok nem támogatják a lebegőpontos bináris műveletek elvégzését. Ha nagy tömegű számítások miatt bináris értékekkel kívánjuk a számítást gyorsan elvégezni, nincs akadája annak, hogy az RPG programban Assembly szubrutin aktivizálását építsük be. Talán nem meglepő, de a változókról sem lehet a megszokott módon írni, hiszen egyrészt jóval egyszerűbb szerkezetek vannak, mint a modern procedurális vagy obj. orientált nyelvekben, másrészt az operációs rendszer támogatásával jóval komplexebb lehetőségeink vannak, mint a megszokott környezetekben. A típusok egészen egyszerűen azért vannak, hogy a rendszer a memóriában le tudjon foglalni megfelelő számú byte-ot a változóknak. Ezen kívül annyit kell tudnia a rendszernek egy típusról, hogy az karakteres-e, decimális (megfelelő számú decimális pozícióval a tizedespont után), bináris, pakolt vagy zónázott decimális-e, megelőző vagy követő előjellel. A változók deklarációja történhet akkor, amikor a fájlszerkezetet megadjuk az ún. file specification részben, ekkor egy rekordnevet deklaráltunk, hozzarendelődik annak mérete, majd ezután a rekord mezőit szekvenciálisan letárolja, és kezdő ill. végpozíciójukat megszámozza. A rekord mezői sima változók, mindenféle minősítés nélkül hivatkozhatunk rá. Általában a mezőnevek az egész rendszerre nézve egyediek, de ha nem, akkor sincs probléma többszörös deklaráció esetén akkor, ha ugyanolyan "típusú" (jobb a szignatura kifejezés) mindegyik deklaráció. A használt változókat azért deklarálni kell valahol, esetleg az első használatkor, pl.

 C Z-ADD0 X 50

Ahol az X változót 0 kezdőértékkel létrehoztuk, az X változó 5 byte hosszú, 0 decimális pozicióval. Nem problémázik a rendszer akkor sem, ha nem az első előforduláskor deklarálunk egy változót, ha ő fordítás közben ki tudja deríteni, mi a típusa a változónak, akkor elfogadja. Még olyan esetet is láthatunk olykor, hogy egy változónak értéket adunk, mégpedig úgy, hogy az egyik változó típusa ismert, ekkor a másik változó típusát is erre állitja a rendszer. Lehetőség van egyébként utasítással más változó mintájára változót létrehozni, pl.

 C *LIKE DEFN X SAVX 

Ekkor a SAVX változó az X mintájára jön létre. Egyszoval az RPG nem erősen típusos nyelv. Az erőforrások védelmét alacsonyabb szinten teszi lehetővé az OS/400 operációs rendszer.

Hatókör

Egy definíció hatóköre függ attól, hogy a definíció hol történik. A nyelv megkülönböztet lokális és globális hatókört. A főprocedúrában definiált változók globálisak, és a modulon belüli (al)program(ok)on belül tetszőlegesen használhatók. Ugyanakkora az alprogramokban definiált változók lokálisak, és csak az adott alprogramon belül használhatók és láthatók.

A fenti szabályok alól két kivétel van:

Változók tárterülete

A lokális változók automatikus tárterületen foglalódnak, a globális változók pedig statikus tárterületen. A STATIC kulcsszó megadásával elérhetjük, hogy egy lokális változó statikus tárterületen jöjjön létre.

Konstansok

Literálokat és konstansokat írhatunk C kártyák factor1, factor2, extended factor2 mezőibe, op-code-ok és függvények paramétereiként, tömbindexként, ill. output specifikációk néhány mezőjébe.

Elnevezett (named) konstansok

Egy D-kártyán adhatunk nevet is konstansainknak (a CONST kulcsszó használata nem kötelező). Pl.:

D DateConst      C              CONST(D'1988-09-03'(
D StrConst       C              'FOOBAR'
	
Beépített (figured) konstansok

Használhatunk néhány az RPG által nyújtott konstanst is, amik hosszát meg sem kell adnunk, mert az mindig automatikusan illeszkedik az adott mezőéhez (*BLANKS, *ZEROS). A nyelv többek közt az alábbi figured konstansokkal kedveskedik a programozóknak:

Variáns rekord alapvetően nincs a nyelvben, de azért hasonló dolgot készíthetünk.

Kifejezések, operátorok

Kifejezések

Mint azt már említettük, az RPG IV-es verziójától a /FREE compiler direktíva használatával a C kártyákon szabadon indentálhatóan kódolhatunk. Így az RPG hagyományos, kizárólag op-code-okkal leírt, kötött kifejezései helyett szabadabb, áttekinthetőbb, operátorokkal fűszerezett kifejezéseket írhatunk. Kifejezéseket a következő (már részben ismertetett) helyeken használhatunk:

Operátorok

Unáris operátorok
Bináris operátorok
Kiértékelési sorrend, precedencia

Az operátorok általában balról jobbra értékelődnek ki, kivéve a **-t, ami jobbról balra. Az operandusok viszont nem feltétlenül balról jobbra értékelődnek ki. A precedenciasorrend:

  1. ()
  2. Built-in functions, user-defined functions
  3. unary +, unary -, NOT
  4. **
  5. *, /
  6. binary +, binary -
  7. =, <>, >, >=, <, <=
  8. AND
  9. OR