Az Aikido programozási nyelv

Kivételkezelés

Kivételkezelési mechanizmus

Az Aikido nyelvbe épített mechanizmussal segíti a kivételkezelést (C++ és Java alapú). Az alapötlet, hogy ha nem várt esemény történik, egy kivétel objektum váltódik ki az adott helyen. A kivétel a hívási vermen keresztül továbbítódik egészen az első olyan függvényig, ami a megfelelő módon kezeli a helyzetet. Ha egy kivételkezelőhöz ért, az kezelheti helyben, illetve továbbdobhatja a kivétel objektumot. Ha a hívási lánc végére értünk, és a kivételt nem kezeltük sehol, a program terminál.

Kivételek kiváltása és elkapása

A kivételek kiváltására a throw utasítást, elkapásukra a try - catch blokkot.

Példa:

try { login(user, password) System.println("User" + user.getName() + " logged in") service(user) } catch (e) { log("Login for + " user.getName() + " failed due to: " + e) return }
A try blokkon belül meghívjuk a login() függvényt, ami egy felhasználót és egy jelszót kap paraméterként. Ha a bejelentkezés sikeres, a servive() függvény is meghívódik. Ha a bejelentkezés sikertelen (például rossz jelszót adtunk meg), a kivételkezelőhöz kerül a végrehajtás. A kivételkezelő elkapja a dobott kivételt (e) , és loggolja a probléma okát.

A C++-szal vagy Java-val ellentétben, az Aikidoban csak egy catch ág lehet - a nyelv dinamikus típusossága miatt. Ez a mechanizmus nem kevésbé használható, mint az említett nyelvekben lévő, csak más jellegű. A C++-ban a típusösszehasonlítás a kivétel kiváltása és a kivétel elkapása között történik. A kivételkezelő csak akkor hívódik meg, ha a kivétel típusa megegyezik a várt típussal. Ezzel szemben az Aikido-ban mindig meghívódik a kivételkezelő, átadva a kivétel "típusának" meghatározását a kivételkezelő kódnak.

Példa:
const BAD_PASSWORD = 1 //password mismatch const TOO_MANY_USERS = 2 //too many users logged in const USER_BARRED = 3 //user has been barred from logging in today try { login() //try to log in //etc. } catch (e) { if(typeof(e) == typeof(int) && e < 0) { //test for type and value System.println("server failure, have to exit") System.exit(e) } elif (typeof(e) == typeof(int)) { switch(e) { case BAD_PASSWORD: System.println("Invalid password, try again") continue //allow a retry case TOO_MANY_USERS: System.println ("Too many users, try again later") return case USER_BARRED: System.println ("You are barred, try again tomorrow") return } }elif (typeof (e) == "string") { //got a string? System.println ("Failed to login due to: " + e) return }else { throw e //rethrow exception to caller } }
Az Aikido-ban bármilyen értéken használhatunk kivételként. Az alábbi kivételdobások mind megengedettek:
throw 1 //an integer 1 throw "invalid password" //a string throw InvalidPassword() //an object throw getException(1) //something returned from a function throw false throw null throw new Exception("Invalid password") throw InvalidPassword //a class

Kezeletlen kivételek

Mi történik, ha egy kivétel a hívási lánc végére ér? Definiáljuk először mit is jelent a végrehajtási verem.

A programban minden szál fenntart egy saját vermet. A végrehajtás minden pontján a verem információkat tartalmaz az aktuális állapotról (pl. a visszatérési értéket, a lokális változókat, stb).

A végrehajtási veremnek van alja és teteje. Az alján a szál által először hívott függvény (illetve maga a szál függvény) van. A verem teteje folyton változik, de mindig az aktuálisan vérehajtott függvényről tartalmaz információt.
Amikor egy kivétel keletkezik, a végrehajtó szál a verem tetejétől indulva keresi a kivételkezelő kódot. Minden alkalommal, mikor egy szinttel lejebb haladunk a veremben, az éppen elhagyott rész kikerül a veremből (megsemmisülnek a lokális változók, stb).
Ha elérjük a verem alját anélkül, hogy a kivételt elkaptuk volna, akkor a program befejezi a futást (nem csak az aktuális szál terminál, hanem minden futó szál és ezáltal az egész program).
A kezeletlen kivételek hatására az interpreter a "runtime error" üzenetet írja a standard error stream-re.

Kivételek és futásidejű hibák

Az Aikido program futásakor vannak olyan esetek, amikor maga az interpreter dob kivételt. Ezek ugyan úgy elkaphatók mielőtt a program abortálását okoznák, mint bármely más kivétel.

Az interpreter által dobott kivételek típusa lehet string vagy a System.Exception osztály (vagy belőle származó osztály) egy példánya.

Például, a System csomag openin() függvénye megkísérel megnyitni egy fájlt, és siker esetén egy streammel tér vissza. Sikertelen próbálkozás esetén (pl. nem létezik a fájl, nem elérhető, stb) az openin() függvény System.FileException típusú kivételt dob.
Példa:

try { var instream = System.openin("chatrc") processRCFile(instream) } catch (e) { //can't open file, ignore }