A Limbo programozási nyelv

Típusok, típuskonstrukciók

Beépített adattípusok

A beépített adattípusok két csoportba sorolhatók:

Primitív típusok


A bájtok (byte) előjel nélküli 8-bites egységek.
Az egészek (int) 32-bites előjeles egységek kettes komplemensben lévő számábrázolással.
A nagyméretű egészek (big) 64-bites előjeles mennyiségek kettes komplemensben lévő számábrázolással.
A valós számok (real) 64-bites egységek IEEE long lebegőpontos számábrázolással.
A byte,int,big, and real típusokat egységesen aritmetikai típusoknak nevezik.


A sztringek (string) Unicode karakterekből álló sorozatok (tömbök). Minden Unicode karakter 16 bit.
Példa:

s := "Inferno";

Karakterenként összefűzhetők és kiegészíthetők.

A nyelvben nincs külön karakter típus. A karaktereket az int értékükkel reprezentálták.
Példa:
c := 'I'; # c értéke 73 (az I betű int értéke)

Sztringből képezhetünk részsztringeket (lásd: tömböknél).

Referencia típusok

A Limbo referencia típusai hasonlóak más nyelvek (pl. C, C++) mutató típusaihoz. A különbség elsősorban az, hogy a Limbo nem engedi meg referenciákon matamatikai műveletek végzését. Ez biztosítja a "pointer biztonságot" a nyelvben, mivel a referencia sohasem mutathat illegális címre. Mégis, az értéke lehet nil.

A nil speciális érték, ami eltünteti a hivatkozást és a hozzátartozó területet. Ha ez az utolsó hivatkozás az adatra, akkor a szemétgyűjtő automatikusan és azonnal felszabadítja az általa foglalt helyet.

Tömb típus

A tömbök rendezett, indexelt, homogén adatokból állnak. Az indexelés 0-val kezdődik.
Alap tömb deklaráció a következő módon néz ki:

buf : array of byte; # buf változó byte típusú elemekből álló tömb

Helyfoglalása és a változónak értékül adás:
buf = array[80] of byte; # a buf tömb 80 db, byte típusú elemekből áll

Lehetőség van a deklarációban 0-re inicializálni a tömböt:
buf := array[80] of byte;

A tömb mérete nem a típusnak, hanem az értékének a része. Az elemek típusa is lehet tömb, ilymódon írhatók többdimenziós tömbök.

A tömbökből és sztringekből képezhetünk ún. szeleteket, melyek összefüggő részét képezik az eredetinek. A kivágandó rész kezdetét és végét jelző indexet zárójelben adhatjuk meg, vesszővel elválasztva. Az kezdeti index által mutatott elem igen, a vég által mutatott nem kerül bele a szeletbe.
Példa:
s := "Inferno"; # s szelete a 2-tól a 6. karakterig: s2 := s[2:6]; # s2 értéke: "fern".

Lista típus

A listák rendezett, nem indexelt, homogén elemekből állnak. A lista első eleme a fej, a maradéka pedig a törzs.

Deklaráció:

line: list of string; # line azonosító sztringekből álló lista

Lista készítéséhez használható a lista konstruktor ( :: operátor):

line = "First" :: line; # "First" a lista feje

A lista konstruktor jobbasszociatív. A bal oldali elem típusának meg kell egyezni a lista elemtípusával. A jobb oldali elem a lista azonosítója.

Alternatív konstruktor a list of:

triple := list of {1, 2, 3}; # tripel lista három eleme:1, 2 és 3

A lista veremszerű szerkezet, melyet a következő műveletre optimalizáltak: fej lekérdezése, törzs lekérdezése, elem beszúrása az első helyre.

Lista fejének lekérdezéséhez használhatjuk a hd operátort. Ekkor nem jön létre új lista és a régi sem változik.
Példa: a fent létrehozott line listát használva:

sys->print("A lista feje a következő: %s", hd line);

utasítás eredménye a következő sor:

A lista feje a következő: First

A lista törzse maga is egy lista, melynek típusa megegyezik az eredeti listáéval. A tl operátort használva az eredeti lista első eleme elhagyható:

line = tl line;

és így akár új lista is létrehozható:

args := tl line;

Sor típus

A sor típus kettő vagy több objektum rendezett együttese, melyek saját adattípussal rendelkeznek. A tagok típusa az egyes sorokban rögzített és megegyezik.
Példa:

retcode := (0, "Érték"); # a retcode sor két eleme 0 és "Érték" sztring

A sor egyes tagjainak értékét értékül adhatjuk más azonosítóknak:
Példa:
err: int; msg: string; (err, msg) = retcode; # inicializálás, az err változó értéke 0, az msg változó értéke "Érték" lesz (err, msg) := retcode; # értékadás

A nil kulcsszó használatával figyelmen hagyhatjuk a sor egy részét:
Példa:
(err, nil) = retcode; # az err változót 0-ra inicializáljuk

Mutatók


A Limbo nyelvben nincsenek mutatók, csak referenciák, amik a ref kulcsszóval hozhatók létre. Nincs & (cím) operátor, nincs mutatóaritmetika, és a referenciák csak absztrakt adattípusú (ADT) objektumra mutathatnak.
Ha e egy ref ADT típusú kifejezés, akkor az ADT értékét a * e utasítással kérdezhetjük le. Az e értéke nem lehet nil.
A szemétgyűjtés automatikus.

Típusok ekvivalenciája

Két alap típus akkor és csak akkor ekvivalens egymással, ha azonosak.

Két sor típus akkor és csak akkor ekvivalens egymással, ha azonos típusú elemekből állnak, és azok sorrendje megegyezik.

Két tömb típus akkor és csak akkor ekvivalens egymással, ha azonos típusú elemekből állnak. A tömb mérete nem része a típusnak.

Két lista típus akkor és csak akkor ekvivalens egymással, ha azonos típusú elemekből állnak.

Két csatorna típus akkor és csak akkor ekvivalens egymással, ha azonos típusú elemek közlekednek rajtuk.

Két ADT típus akkor és csak akkor ekvivalens egymással, ha adattagjaik neve azonos és típusuk ekvivalens. A tagok deklarálásának sorrendje közönbös, és a tagfüggvények, a konstansok és az ADT típusának neve sem vesznek részt az összehasonlításban.
Példa:

A: adt { x: ref B; }; B: adt { x: ref A; };


esetén A és B típusok ekvivalensek

Két ref ADT típus akkor és csak akkor ekvivalens egymással, ha ekvivalens ADT típusokra hivatkozó referenciák.

Két modul típus akkor és csak akkor ekvivalens egymással, ha a tagfüggvényeik és adataik neve megegyezik és típusuk azonos; a deklarálási sorrend közönbös. A konstansok és típusok nem számítanak az összehasonlításban.

Két függvény típus akkor és csak akkor ekvivalens egymással, ha visszatérési értékük azonos típusú és paramétereik ekvivalens típusúak.

Típuskonverziók

A nyelvben nincs automatikus típuskonverzió, minden típuskényszerítést explicit meg kell adni.

Változók, konstansok

Változók

A deklaráció általános alakja:

azonosító-lista : típus ; azonosító-lista : típus = kifejezés ;

Azonosítók vesszővel elválasztott listáját kettőspont, majd a típus neve követi. Ha a deklarációban szerepel = és kifejezés, a típus adattípus kell legyen, és minden objektum a kifejezés értéke szerint inicializálódik. A legfelső szintű (függvényen kívüli) deklaráció során a kifejezés lehet konstans vagy olyan tömb, melyet konstans kifejezéssel hoztunk létre.
A listák és ref ADT típusok nem inicializálhatók a legfelső szinten. Ha egy objektumot nem inicializáltuk explicit, és referencia típusú, akkor nil-re inicializálódik. Ha aritmetikai típusú, a legfelső szinten 0-ra inicializálódik, függvénybeli előfordulása esetén pedik az értéke definiálatlan lesz.
Példa:
i, j: int = 1; r, s: real = 1.0;

A fenti deklaráció hatására i és j egész, r és s valós változók; i és j értéke 1, r és s értéke 1.0.

A deklaráció másik formája a gyorsírás.

azonosító := kifejezés ; ( azonosító-lista ) := kifejezés ;

A bal oldali azonosítók mindegyikét a a kifejezés típusát felhasználva deklaráltuk, és a kifejezés értéke alapján inicializáltuk. A második esetben a kifejezés sor vagy ADT lehet, és az változók típusa és értéke megegyezik a sor megfelelő tagjával vagy az ADT megfelelő adattagjával. Példa:

x: int = 1; x := 1;

A fenti két utasítás ugyanazt eredményezi. Hasonlóan:

(p, q) := (1, 2.1);

a baloldali p ill. q változókat egész ill. valós értékűre deklarálja, értékük 1 ill. 2.1 lesz. A :=-vel jelölt deklarációk kifejezések is lehetnek.

Láthatóság, elérhetőség

Egy változó láthatósága attól függ, hogy hol lett deklarálva.

Konstansok

Primitív típusú, konstans értékkel rendelkező azonosítók a con kulcsszóval deklarálhatók.
Példák:

data: con "/data/user.dat"; # sztring konstans block: con 512; # egész konstans pi: con 3.1415926535897932; # valós konstans

Konstans felsorolások

A C felsorolás típusához hasonló típust hozhatunk létre, ha a con kulcsszót a speciális iota értékkel kombináljuk:
Példa:

Sun, Mon, Tue, Wed, Thu, Fri, Sat: con iota;

A fenti utasítás hatására a Sun konstans értéke 0 lesz, a Mon konstansé 1, és így tovább.

A kezdeti érték megváltoztatására ill. az érték növelésére az iota mellett más operátorokat használunk. A leggyakrabban használt operátorok az összeadás(+), szorzás(*), és bitenkénti léptetés (<< és >>).
Példák:
Ten, Eleven, Twelve: con iota+10; Zero, Five, Ten, Fifteen: con iota*5; Two, Four, Eight, Sixteen, ThirtyTwo: con 2<<iota;

Kifejezések, operátorok

Kifejezések

A kifejezés általános alakja:

kifejezés: bináris-kifejezés balérték-kifejezés értékadó-operátor kifejezés ( balérték-kifejezés-lista ) = kifejezés send-kifejezés declare-kifejezés load-kifejezés

Egyoperandusú kifejezések

Az egyoperandusú kifejezés egyoperandusú operátort tartalmazó kifejezés.
Általános alakja:

egyoperandusú-kifejezés: term egyoperandusú-operátor egyoperandusú-kifejezés array [ kifejezés ] of adat-típus array [ kifejezésopt ] of { init-lista } list of { kifejezés-lista } chan of adat-típus adat-típus egyoperandusú-kifejezés

Egyoperandusú operátorok

-

negatív előjel, aritmetikai típusra alkalmazható

+

pozitív előjel, aritmetikai típusra alkalmazható

!

logikai negáció, int típusú operandusra, ha az érték 0, akkor 1-re állítja, különben 0-ra

~

int vagy byte típusú operandusa egyes komplemensét adja vissza

ref

adt típusú e kifejezésből ref adt típusú kifejezést hoz létre, melynek értéke referencia egy e értékű névtelen objektumra

*

* e a ref adt típusú e kifejezés értéke. Az e értéke nem lehet nil.

++

prefix v. postfix inkrementálás

--

prefix v. postfix dekrementálás

<-

lásd: csatorna kommunikáció

hd

lásd: listáknál

tl

lásd: listáknál

len

sztring, tömb vagy lista elemeinek a száma

Bináris kifejezések

A bináris kifejezés vagy egyoperandusú kifejezés vagy olyan kétoperandusú, melyben szerepel egy infix operátor.
Általános alakja:

bináris-kifejezés: egyoperandusú-kifejezés bináris-kifejezés bináris-operátor bináris-kifejezés

Bináris operátorok

A bináris, kétoperandusú operátorok precedencia szerinti csökkenő sorrendben:

*, /, %

szorzás, osztás, maradékképzés
Az operandusok azonos aritmetikai típusúak, az eredmény megegyezik az operandusok típusával.
A % nem alkalmazható a real típusra.
A túlcsordulás és 0-val való osztás eredménye definiálatlan.
|a%b| < |b|; (a/b)*b + a%b értéke a ; a >= 0, b >= 0 esetén (a%b) >= 0

+, -

összeadás, kivonás
Az operandusok típusa azonos kell legyen, az eredmény megegyezik az operandusok típusával.
Alul- és túlcsordulás esetén az eredmény definiálatlan.
A + operátor sztringek esetén konkatenációt jelent.

<<, >>

bal-, ill. jobboldali léptetés
A bal oldali operandus típusa lehet big, int vagy byte, a jobb oldali int típusú. Az eredmény típusa megegyezik a bal oldali operanduséval. A jobb oldali operandus értéke nem lehet negatív, és kevesebb kell legyen, mint a bal oldali operandus bitjeinek száma.
<< operátor esetén a kitöltött bitek értéke 0, >> operátor esetén int esetben a jelek másolata, byte esetben 0.

<, >, <=, >=

kisebb, nagyobb, kisebb vagy egyenlő, nagyobb vagy egyenlő
Csak aritmetikai típusokra és sztringekre alkalmazhatók. Az operandusoknak azonos típusúnak kell lenni, a sztring értéke lehet nil. A sztringen végzett összehasonlítás lexikografikus az Unicode karakterkészleten. Egy inicializálatlan vagy nil-re inicializált sztring megegyezik a "" üres sztringgel minden összehasonlító operátornál.

==, !=

egyenlő, nem egyenlő
Az operandusok típusa lehet aritmetikai, sztring vagy referencia típus. Általában az operandusok típusának egyeznie kell, de a sztringek és referencia típusok értéke lehet nil. Referencia típusú objektumok akkor egyenlők, ha ugyanarra az objektumra mutatnak, vagy mindkettő értéke nil.

&

bitenkénti logikai és
Operandusai azonos típusúak. Ez a típus lehet: byte, int vagy big.
Az eredmény bitenkénti végrehajtás útján jön létre.

^

bitenkénti logikai kizáró vagy
Operandusai azonos típusúak. Ez a típus lehet: byte, int vagy big.
Az eredmény bitenkénti végrehajtás útján jön létre.

|

bitenkénti logikai vagy
Operandusai azonos típusúak. Ez a típus lehet: byte, int vagy big.
Az eredmény bitenkénti végrehajtás útján jön létre.

::

lista konkatenáció

&&

logikai és
Először a bal oldali operandus értékelődik ki. Ha ez az érték 0, az egész kifejezés értéke 0 (int típusú). Különben a jobb oldali operandus is kiértékelésre kerül, és ha értéke 0, az egész kifejezés értéke is 0 lesz, különben 1. Az operandusoknak azonos aritmetikai típusúnak kell lenniük.

||

logikai vagy
Először a bal oldali operandus értékelődik ki. Ha ez az érték nem nulla, az egész kifejezés értéke 1 (int típusú) lesz. Különben a jobb oldali operandus is kiértékelésre kerül, és ha értéke nem nulla, az egész kifejezés értéke is 1 lesz, különben 0. Az operandusoknak azonos aritmetikai típusúnak kell lenniük.


A :: operátort kivéve (mely jobbasszociatív) a fenti operátorok mindegyike balasszociatív.