Szintaxis
A Limbo alprogramjai ugyanazon célt szolgálják, mint más strukturált, procedurális nyelvek alprogramjai: a program futása során végrehajtott utasításokat tartalmazzák.
A Limbo függvény általános alakja:
függvény_név(paraméterek): visszatérési_típus
{
utasítás
}
Az
paraméterek változó nevek és hozzájuk társított típusok vesszővel elválasztott listája.
A függvény meghívásakor behelyettesítődnek a függvénybe. A függvénynek nem kötelező, hogy legyen paramétere, de üres zárójelpárt ekkor is írni kell a
függvény_név mögé.
A
vissztérési_típus határozza meg a visszatérési érték típusát, ami tetszőleges lehet. A függvénynek nem kötelező értékkel visszatérnie.
Az init függvény
Ha a programot Inferno shellből hajtjuk végre, a shell egy speciális, init-nek nevezett függvényt keres. Ez a függvény mondja meg a rendszernek, hol kezdődik a program végrehajtása. Bizonyos szemszögből a C
main függvényének felel meg.
Az init függvénynek két paramétere van: ref Draw->Context és
list of string.
ref Draw->Context
ref Draw->Context a képernyő adatainak kinyerésére szolgál, és a draw.m-ben definiálták. Ez az
paraméter megadása akkor is kötelező, ha a program nem használ semmilyen grafikát. Ha nem használjuk,
nil-re állíthatjuk.
list of string
A list of string parancssorból a modulhoz adható paraméterek listája.
Ha a program nem használ parancssorban megadott paramétereket, nil-re állítható.
E függvény működését tekintve ekvivalens a C argv változójával.
Függvények deklarálása
A modul minden publikus függvényét deklarálni kell. A deklaráció hasonló a
C és C++-beli függvény prototípusok deklarációjához. Meg kell adni a paraméterekre és a visszatérési érték típusára vonatkozó információkat. Ez lehetővé teszi a
fordító számára a típusellenőrzést, ami biztosítja futási időben a típusbiztonságot.
A deklaráció általános alakja a következő:
function_name: fn(arguments): return_type;
A függvénydeklaráció hasonló az adatdeklarációhoz. Az
fn kulcsszó jelzi, hogy az objektum "függvény" típusú.
A modulban nem deklarált függvények privát tagok. Külső modulból nem érhetők el. A
fordító elvégzi a típus ellenőrzést a függvényhívások és függvénydefiníció ellenére is.
A következő példa egy olyan modul, amely két függvényt tartalmaz: a publikus
init és egy
privát függvényt.
implement Command;
include "sys.m";
sys: Sys;
include "draw.m";
Command: module
{
init: fn(nil: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
for(i := 1; i <= 10; i++) {
sys->print(" %2d %4d\n", i, sqr(i));
}
sqr(n: int): int
{
return n*n;
}
Függvény paraméterek
Ha a függvény rendelkezik paraméterekkel, átmeneti változókat kell deklarálnia, melyek felveszik
a paraméterek értékét. A paraméterek a függvény belsejében úgy viselkednek, mint más lokális változók. A függvénybe való belépéskor jönnek létre, és a függvényből való kilépéskor megsemmisülnek.
Mivel a Limbo erősen típusos nyelv, a fordító ellenőrzi az paraméterek típusát a függvény deklarációjában, a definíciójában, és a meghívásakor is.
Ha ezek közül valamelyik nem egyezik meg, a fordító hibát jelez.
Érték ill. referencia szerinti paraméterátadás
Mivel a Limbo nem engedélyezi a pointerek használatát, ezért nincs általános referencia szerinti hívás/átadás mechanizmus. A referencia típusú paraméterek referencia szerint, minden más típusú
paraméter érték szerint adódik át.
Ha az adat érték szerint adódik át, a fogadó függvény egy teljesen új változót hoz létre, ami tartalmazni fogja az átadott értéket. Ezen változó módosítása nem hat ki a hívó függvénybeli értékre.
Ha az adat referencia szerint adódik át a fogadó függvény megkapja a referenciát, ami az átadott
paraméter értékére mutat. Az adat módosítása a hívó függvénybeli értéket is megváltoztatja.
Függvény visszatérési értékek
Mint korábban említettük, a függvénynek lehet (de nem kötelező) visszatérési értéke.
A return utasítás
Függvényből való visszatérésre használjuk. Visszaadja a vezérlést a hívó függvénynek. A végrehajtás a hívás után folytatódik. Ha a függvénynek van visszatérési érte,
szerepelnie kell benne a return utasításnak.
A return utasításban szerepelhet kifejezés, ennek értéke lesz a függvény visszetérési értéke. A kifejezés értékének azonos típusúnak kell lennie a deklarációban szereplő visszatérési típussal.
Példa: a fenti példák egyikében szereplő sqr függvény return utasítást használ az
paraméterként átadott szám négyzetével való visszatéréshez:
sqr(n: int): int
{
return n*n;
}
Modulok
A modul típus név egy azonosító.
modul-típus:
azonosító
Az
azonosítót modul azonosítóként deklaráljuk a modul deklarációban,
ami magába foglalja az ADT-k, függvények, konstansok és beépített típusok deklarációit. A modul típusú objektum a modul kezelésére szolgál, és a modul függvényeinek elérésére használjuk.
A modul deklarációja után az
azonosító a modul típusának neve lesz.
Példa:
Linear: module {
setflags: fn (flag: int);
TRUNCATE: con 1;
Vector: adt {
v: array of real;
add: fn (v1: self Vector, v2: Vector): Vector;
cross: fn (v1: self Vector, v2: Vector): Vector;
dot: fn (v1: self Vector, v2: Vector);
make: fn (a: array of real): Vector;
};
Matrix: adt {
m: array of array of real;
add: fn (m1: self Matrix, m2: Matrix): Matrix;
mul: fn (m1: self Matrix, m2: Matrix): Matrix;
make: fn (a: array of array of real): Matrix;
};
};
A fenti kódrészlet egy lineáris algebrai csomag modul deklarációja, mely két ADT-t implementál
(
Vector és
Matrix), szerepel benne egy konstans, és a s
etflags függvény. A
Linear név a modul típus neve, és a modul egy példányának deklarálására használható:
linearmodule: Linear;
Mielőtt a modult használni tudnánk, be kell tölteni, például a következő módon:
linearmodule = load Linear "/usr/dmr/limbo/linear.dis";
if (linearmodule == nil) {
sys->print("Can't load Linear\n");
exit;
}
A modul deklarációban deklarált adatok inicializálása a legfelső szinten egy értékadó utasítással történik. Például:
implement testmod;
testmod: module {
num: int;
};
. . .
num = 5;
Az értékadás jobb oldalán
konstans kifejezésnek kell szerepelnie.
A load operátor
A load kifejezés általános alakja:
load-kifejezés:
load azonosító kifejezés
Az
azonosító a modul azonosítója (a module deklarációban deklarált típus neve). A load utáni
kifejezés sztring típusú, a modul lefordított alakját tartalmazó fálj neve.
A load futtatása során a modult tartalmazó fájl bekerül a helyi memóriába, és dinamikusan típuselleneőrzést végez az interfészen: a futás idejű rendszer kideríti, hogy a modul által exportált deklarációk kompatibilisek-e a
load operátor érvényességi tartományában szereplő modul deklarációval.
Ha a betöltési kísérlet meghiúsul, a
load értéke
nil lesz. A kísérlet meghiúsulhat, ha a
modult tartalmazó fájl nem található meg, vagy ha a megtalált modul nem exportálja a kívánt felületet.
A
load minden kiértékelése során a megnevezett modul egy új példánya jön létre, mely nem osztozik adatain a többi példánnyal.