A Theta programozási nyelv

Függvényhívások

A Theta-ban két fajtája van a rutinoknak. A procedúrák egy vagy több objektum összességét adják vissza. Az iterátorok adatok sorozatát adják vissza (ahol egy adat, egy vagy több objektum összessége), egyidőben egy adatot. Iterátort hívni (csak) egy for ciklusban lehet, és a for ciklus törzsét végrehajtja minden adatra a sorozatban.

Egy rutin hívása során a rutin végrehajtódik az argumentumában szereplő objektumokkal. Ebben a fejezetben megtárgyaljuk a hívási mechanizmus egy részét, ami közös a procedúráknál és iterátoroknál egyaránt (és maker-eknél is).

A egyedül álló rutinokat a specifikációval definiáljuk; Így a specifikációk paraméterezhetjük, ily módon példányosíthatunk egy rutint. Rutinokat kifejezések kiértékelésével is kaphatunk. Például, ha egy rutin úgy kapunk meg, hogy kiválasztjuk az objektum egy metódusát, vagy megadunk egy rutint néhány aktuális argumentummal.

A függvényhívás formája

A hívások a következő formával rendelkeznek:

        <invoc> -> <expr0> "(" [<args>] ")"

ahol

<args> -> <expr> ["," <expr>]* ["," <varying_args>] | <varying_args>
<varying_args> -> .. | .. <expr> ["," <expr>]*

A "varying_args" forma megengedi, hogy változó számú argumentuma legyen. Ezek az argumentumok együtt egy sorozat elemeit alkotják, amik a hívás (legutóbbi) legutolsó hívásának aktuális argumentumai, és a forma csak akkor megengedett, ha egy rutin hívásakor ezek az argumentumok sorozatot alkotnak.

Egy hívásnál végrehajtásánál végrehajtódó tevékenységek sorozata a következő:

  1. Az expr kifejezések (beleértve expr0-t is) nem meghatározott sorrendben lesznek kiértékelve.
  2. Az expr0 kifejezést procedúra vagy iterátor segítségével kell kiszámolni.
  3. Új változók lesznek bevezetve a meghívott rutin formális argumentumainak megfelelően (ebbe az új környezetben lesz végrehajtva a rutin)
  4. A nem változó argumentumok kiértékelésével kapott objektum visszatérési értékek hozzárendelődnek a megfelelő új változókhoz (a formális argumentumokhoz). Az első formális argumentumhoz az első érték lesz hozzárendelve, a másodikhoz a második, és így tovább. Minden kifejezés típusa altípusa kell legyen megfelelő formális argumentum típusának.
  5. Ha a "varying_arg"-t használtuk, akkor az utolsó argumentuma a rutinnal "sequence[T]" típusúnak kell hogy legyen, és minden "varying_arg" típusa altípusa kell legyen T-nek. A "varying_arg"-ok kiszámításával kapott objektum visszatérési értékek egy "sequence[T]" konstrukciót alkotnak, az első "varying_arg" az első elem, stb, és a sorozat hozzárendelődik az utolsó formális argumentumhoz.
  6. A vezérlés átadódik a rutinnak, ami a törzsével kezdődik.

A hívás pontosan azokban az esetekben megengedett, amikor a formális és aktuális argumentumok száma megegyezik (miután létrehoztuk a "varying_arg"-ból a sorozatot), és az aktuális kifejezések hozzárendelése a formálisokhoz megengedett.

Például, ha a "p" procedúra a következő szignatúrával rendelkezik:

proc (int, sequence[int]) returns (sequence[int])

akkor ezek a hívások megengedettek:

s: sequence[int]
s := p(0,..3,5,7) % A második argumentum egy sorozat a 3, 5, és 7 elemekkel
s := p(6,..) % A második argumentum egy üres sorozat
s := p(5, s) % A második argumentum az s sorozat

 

Megosztás szerinti hívás

A hívó és hívott rutin csak az argumentumokon és a visszatérési értékeken keresztül kommunikál. A rutinok nem férhetnek hozzá a hívó egyetlen változójához sem.

Az aktuális argumentumok kifejezésének a formális paraméterekhez való hozzárendelése után, a hívó és a hívott rutin megosztozik az objektumokon. Ha a hívott rutin módosít egy megosztott objektumon, akkor a módosítás látható lesz a hívó számára is a visszatéréskor. A nevek arra használjuk, hogy megnevezzük a megosztott objektumokat, különbözőek a hivő, és hívott rutinban. Ha egy rutin hozzárendel egy objektumot egy formális argumentum változóhoz, akkor az nincs hatással a hívóra. A hívott rutin szempontjából az egyetlen különbség a formális argumentum változók és a saját lokális változói között az, hogy a formális változóknak a hívó ad kezdeti értéket.

Futási időben történő üzenetküldés (hiba)

Habár a fordító mindenképpen típusbiztonsággal értékel ki egy hívást, mégsem lehet biztosan meghatározni pontosan milyen kód fog végrehajtódni. Nevezetesen, egy metódus hívás esetén a fordító általában csak a nyilvánvaló (statikus) típusát tudja az objektumnak, amelynek a metódusát kiválasztottuk, és nem az aktuális (dinamikus) típusát. Amikor a kód végrehajtódik, meghatározza az aktuális típust, és a saját implementációját használja a típusnak. Emiatt a metódus hívása futási idejű üzenettel (hibával) jár.

Terminálás (befejeződés)

A rutin kétféleképpen terminálhatnak: normális módon, vagy kivétellel, amit egy kivétel üzenete jelez. Ha rutin normális módon fejeződik be, akkor a visszatérési objektumok a hívó rendelkezésére állnak, és mutathat rájuk egy változó vagy továbbadódhatnak egy másik rutin argumentumaként. Ha egy rutin kivétellel feleződik be, akkor a végrehajtási folyamat átadódik egy kivételkezelőnek a hívó rutinban.