A MUMPS programozási nyelv

Utasítások, vezérlési szerkezetek

A MUMPS nyelv nem érzékeny a kis- és nagybetűkre, sőt a parancsokat az értelmezhetőségig le is rövidíthetjük. Így a következő parancsok ekvivalensek. Ha egy parancs után vesszővel elválasztva több argumentumlistát írunk, akkor a parancs balról jobbra minden argumentumlistára lefut.

CLOSE CL C cLoS

Parancsok

A parancsok hatására hajt végre a fordító tényleges utasításokat a rendszeren. Minden MUMPS parancs a szintaxisának megfelelően átadódik az arugmentumaival együtt a fordítónak.
Az ANSI alap MUMPS parancsokhoz az egyes implementációk speciális parancsokat is szoktak implementálni, ezek általában a Z betűvel kezdődő parancsok.

Parancs és parancssor

A parancs egy parancsnévből és az argumentumokból áll. A parancs az argumentumokon fog végrehajtódni. Az argumentumok és a parancsnév egy és csak egy szóközzel vannak egymástól elválasztva. Két parancs között egy parancssorban akár több szóköz is lehet. Ha a parancsnak egynél több argumentumot kell átadnunk, akkor argumentumlistát adunk át a parancsnak. Az argumentumlista argumentumok vesszővel elválasztott véges sorozata. Két argumentum között egy és csak egy vessző állhat. Nem lehet két argumentum között például egy vessző és egy szóköz. Bármelyik parancssor végén állhat egy megjegyzés, melyet egy pontosvesszővel (;) kell kezdeni és a sor végéig fog tartani. A parancsneveket az értelmezhetőségig lehet rövidíteni, tehát a következő két parancs ekvivalens:

WRITE•"Hello vilag","!" W•"Hello vilag","!"

Alapvető parancsok

A parancsok után álló Utófeltétel minden esetben arra szolgál, hogy a parancs csak az utófeltétel teljesülése esetében hajtódjon végre.

NEW
N{EW}
N{EW}{:Utófeltétel}•Változó{,...}
N{EW}{:Utófeltétel}•(Változó{,...})

A NEW paranccsal új változó hozható létre (elfedhető a korábbi értéke). Ilyenkor a már létező, ugyanilyen nevű változók elmentődnek és az első QUIT parancsra visszatöltődnek. Ha nem adunk meg paramétert, akkor az összes változóra vonatkozik a parancs. Ha zárójelben adunk meg változókat, akkor a megadott változókon kívüli változókra lesz alkalmazva a parancs.

KILL
K{ILL} K{ILL}{:Utófeltétel}•Változó{,...} K{ILL}{:Utófeltétel}•(Változó{,...})

Törli a megadott változót.

SET
S{ET}{:Utófeltétel}•Változó=Kifejezés S{ET}{:Utófeltétel}•(Változó{,...}=Kifejezés

A SET parancs értékadásra szolgál. A megadott változó, illetve változók az adott kifejezés értékét veszik fel.

READ
R{EAD}{:Utófeltétel}•Változó{#Hossz}{:Időkorlát} R{EAD}{:Utófeltétel}•*Változó{:Időkorlát}

Beolvas az aktuális eszközről Hossz darab karaktert. Ha nincs Hossz megadva, akkor maximum 255 darab karaktert olvas be. Az olvasás leáll, ha az olvasás elérte a kellő hosszt, vagy lejárt az Időkorlát, vagy a felhasználó lenyomta az entert.

WRITE
W{RITE}{:Utófeltétel}•Formátum W{RITE}{:Utófeltétel}•Kifejezés W{RITE}{:Utófeltétel}•*Egész

A WRITE paranccsal lehet az aktuális eszközre írni. Lehet írni formázó karaktereket, kifejezések, változók értékét. Ha egy csillagot (*) írunk egy egész szám elé, akkor a számnak megfelelő ASCII kódú karaktert írja ki az eszközre a parancs.

XECUTE
X{ECUTE}{:Utófeltétel}•{Kifejezés}{:Utófeltétel2}{,...}

Indirekten végrehajtja a Kifejezés tartalmát. Minden egyes Kifejezésre külön lehet Utófeltétel2-t megadni.

Parancssorok és rutinok

A munka fő egysége a MUMPS nyelvben a parancssor. A parancssor egy, vagy több parancs egyesítése egyetlen sorba. Egy, vagy több parancssor egyesítése a rutin.

Rutin-felépítés

Egy vagy több parancssort egy közös egységbe, egy rutinba zárhatjuk. Ezek után a parancssorokat rutinsoroknak kell nevezni. A rutinsorok felépítése megegyezik a parancssorok felépítésével, azzal a kivétellel, hogy minden rutinsor egy → jellel kezdődik, melyet egy opcionális címke előzhet meg. A címke lehet szám, vagy egy név. Ha név, akkor vagy alfa-karakterrel, vagy %-jellel kell kezdődnie. Az első karakter után alfanumerikus karakterek szerepelhetnek. A címkék lehetnek nyolc karakternél hosszabbak is, de a fordító csak az első nyolc karaktert vizsgálja. Ha egy rutin elkészült, akkor egy ún. rutinnévvel lehet rá később hivatkozni. A rutinnév a rutin első sorának címkéje. A rutinnévre ugyanolyan megkötések élnek, mint a címkékre, kivéve, hogy nem állhat csak számokból. Egy rutinra nagyon sokféleképpen lehet hivatkozni. Ha csak a rutin nevével hivatkozunk, akkor a rutin első sorától kezdődően indul a végrehajtás. De lehet hivatkozni a rutin egy címkéjére is, sőt egy címkétől adott távolságra lévő sorra is. A következő sorok nem parancssorok, hiszen nem paranccsal kezdődnek, ezek érvényes rutin-hivatkozások.

ABC ^ATNEZ 120^TESZT MASIK+10^SAJATPRO

Minden rutin utolsó sorának egy QUIT parancsnak kell lennie. Ezzel a paranccsal lehet ugyanis kilépni a rutinból.

Blokk struktúrált alrutinok

Sok esetben szükséges rutinsorok egységbe zárása, olyan esetben, ahol külön rutinok írása nem szükséges. Ilyen esetek például az elágazások, vagy a ciklusmagok. Ha egy blokkot írunk, akkor a rutinsorban a parancsnév elé egy, vagy több pontot (.) kell tennünk. A pontok száma attól függ, hogy milyen mélyen vagyunk a blokkhierarchiában.
Blokkstruktúrák sorai a következőképpen nézhetnek ki:

Címke → . ... . Parancssor
→ . ... . Parancssor

Például:

I•KOD=10•D .F•I:1:1:3•D ..W•"Hello" ..W•" vilag!","!" E••D .W•"Senki sincs ott.","!"

Vezérlésátadó utasítások

GOTO
G{OTO}{:Utófeltétel1}•Címke{:Utófeltétel2}{,...}

A megadott címkére ugrik, ha az Utófeltétel2 teljesül.

QUIT
Q{UIT}{:Utófeltétel} Q{UIT}{:Utófeltétel}•Kifejezés

Véget vet egy DO, FOR, vagy XECUTE parancs végrehajtásának. Ha egy rutint függvényként hívnak meg, akkor a megadott kifejezést adja vissza a parancs.

Ciklusok

DO
D{O}{:Utófeltétel} D{O}{:Utófeltétel}•Címke{:Utófeltétel2} D{O}{:Utófeltétel}•Címke(Paraméterlista){:Utófeltétel2}

A DO parancs abban különbözik a GOTO parancstól, hogy miután átugrik a megadott címkére, a megfelelő QUIT parancs hatására visszakerül a vezérlés a DO parancs utáni parancsra. A parancs tulajdonképpen egy alprogram hívásának felel meg. Minden egyes címkére külön lehet megadni Utófeltétel2-t, ekkor csak az a rutin hívódik meg, amelyiknek az utófeltétele igaz.

FOR
F{OR} F{OR}•Változó=Paraméter{,...}

A parancs meghatározott számú ismétlést végez a parancssor hátralévő részében lévő parancsokon. Az aktuális ismétlés száma a változóban lesz elérhető. A paraméter háromféle lehet:

A ciklusból QUIT, vagy GOTO paranccsal lehet kilépni. A két kilépési mód között az a lényeges különbség, hogy a GOTO paranccsal akár több FOR ciklusból is kiléphetünk (attól függően, hogy hol van a hivatkozott címke), míg a QUIT paranccsal csak a legbelső ciklusból lépünk ki.
Programkód:

F•I=1:1:9,10:2:20•D•KIIR(i)

Kimenet:

I = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20

Programkód:

F•I=1:5•W•I•I•I=335•Q

Kimenet:

I = 1, 5, 10, ..., 330, 335

Programkód:

F•I=2,-5,10,2,-20•D•ALT(I)

Kimenet:

I = 2, -5, 10, 2, -20

Elágazás

IF
I{F} I{F}•{Kifejezés{,...}}

A parancs a $TEST speciális változó segítségével dönti el, hogy a parancssorban hátralévő parancsokat figyelembe vegye-e a fordító. Ha a $TEST speciális változó értéke 1, akkor hajta végre az utasításokat. Ha van egy, vagy több Kifejezés megadva, akkor a fordító balról jobbra kiértékeli őket, és folyamatosan frissíti a $TEST értékét. A parancssor további részeit csak akkor hajtja végre a fordító, ha mindegyik Kifejezés igaz értéket ad.

ELSE
E{LSE}

A parancs a $TEST speciális változó értékétől függően hajtja végre a parancssorban még hátralévő parancsokat. Ha a $TEST speciális változó értéke 0, akkor végrehajtja az utasításokat. Az ELSE parancs után mindig két szóköznek kell lennie. Nagyon fontos megemlíteni, hogy ez a megoldás nagyon veszélyes lehet és sok esetben nem a kívánt eredményt hozhatja.
Tekintsük például a következő parancssort:

I•I=5•D•RUTIN•E••D•MASIK

Ha a feltétel teljesül, a $TEST speciális változó értéke 1, a RUTIN rutin meg fog hívódni. Miután visszatér, nincs semmi garancia arra, hogy a $TEST speciális változó még mindig 1 értékkel rendelkezik. Lehet, hogy azóta már 0 lett egy másik IF miatt és ebben az esetben az ELSE ág is végrehajtódik, ami természetesen nem az, amit szerettünk volna. Ezt kiküszöbölhetjük úgy, ha nem használjuk az ELSE parancsot, vagy, ha az alábbi trükköt alkalmazzuk:

I•I=5•D•RUTIN•I•1••E••D•MASIK

Ekkor az ELSE előtti IF csak az eredeti elágazás igaz ágában fut le és a $TEST speciális változót mindig 1-re állítja, így a várt eredményt kapjuk.