A CLU programozási nyelv

Bevezetés



2. Változók és kifejezések

2.1. Változók
2.2. Értékek
2.3. Deklaráció 2.3.1. Konstansok
2.3.2. Hatáskörök 2.4. Kifejezések
2.5 Értékadás
2.6. Eljáráshívás


2.1. Változók

A CLU procedurális nyelv, de az eljárásai csak egy szinten definiálhatók (egy másik eljárásban nem), viszont az eljárások tetszőleges mélységben tartalmazhatnak blokkokat, melyekben a változók élettartam és láthatósági jellemzői a blokk-struktúrált nyelveknek megfelelő. (Azaz egy blokkban lehet változókat deklarálni és ezek csak az adott blokkban érvényesek.)

A CLU szigorúan típusos nyelv, egy változó csak olyan típusú értékeket tartalmazhat, amilyen típust a deklarációjában megadtunk. Minden változó kaphat deklaráláskor kezdeti értéket. Ha olyan változóra történik hivatkozás, amelyik még nem kapott a deklarálása óta értéket az mindig futási hibát okoz.

Egy sajátosság, hogy az eljárások (iterációk) is típusok, illetve a megírt eljárás valójában egy literálnak (értéknek) felel meg, a fejléce határozza meg a típusát. Ennél fogva lehetnek ilyen változók, értéket kaphatnak, paraméterként átadhatók, és ezek a változók - megfelelő paraméterezéssel végrehajthatók.

A változók deklarálása a név és a típus megadását jelenti a következő módon:

<variable name> : <type>
Az így definiált változók inicializálatlanok, azaz nem hivatkoznak egyetlen objektumra sem.
A változódeklaráció tartalmazhat inicializálást is:
b : array[int] := a
Ekkor a b változó vagy ugyanarra az objektumra fog hivatkozni, mint az a változó, vagy lemásolódik annak értéke. Ezt a típusa dönti el.
 

2.2 Értékek

A változók értékei objektumok, melyek kétfélék lehetnek: mutable és immutable.

A mutable objektumok valódi objektumok, a rájuk hivatkozó változóban csak a hivatkozás (referencia) tárolódik. (Olyasmi, mint egy pointer.) Egy mutable objektumra több hivatkozás is mutathat egyszerre - ekkor osztott objektumnak hívjuk. Ilyen típusú változók értékadásakor mindig csak hivatkozás adódik át, ha a teljes objektumot szeretnénk átadni, akkor arra többnyire valamilyen copy eljárás szolgál. A mutable objektumokat egy konstruktor művelettel kell létrehozni.

Az immutable objektumoknak nem a hivatkozása tárolódik, hanem maga az egész objektum. (Klasszikus  példák az egyszerű típusok, pl. az egész vagy logikai értékek.) Egy immutable objektumra nem történhet többszörös hivatkozás, azaz nem lehetnek osztottak. Az ilyen típusú változók értékadásakor mindig lemásolódik az érték. Az immutable objektumoknak deklaráláskor - egy nem specifikált - default értékkel létrejönnek maguktól.

A konstansok csak immutable objektumok lehetnek, ez garantálja, hogy értékük nem változik meg.

Az egyszerű alaptípusoknak csak immutable, az típuskonstukciókkal definiáltaknak van immutable és mutable változata is.

2.3. Deklaráció

Azonosítókat használunk az objektumokra való hivatkozásra. Az azonosító lehet konstans, amely csak egy előre adott objektumra hivatkozhat, vagy változó, amely az idő folyamán hivatkozhat más-más objektumra. Mind a konstansokat, mind a változókat deklarálni kell, és mindegyikhez tartozik egy típus, amit a deklaráció során kell megadni.

A CLU típusellenőrző mechanizmusa biztosítja, hogy minden konstans illetve változó csak a típusának megfelelő típusú objektumra hivatkozhat.

2.3.1. Konstansok

A konstansokat egyenlőséggel definiálhatjuk (pl.: x = 3). A CLU-konstansok csak beépített immutable típusokra hivatkozhatnak. Ez a megszorítás garantálja, hogy a konstans tényleg nem változhat meg, azaz mindig ugyanarra az objektumra hivatkozik, és a hivatkozott objektum értéke sem változik az idő folyamán. A konstans értékét definiáló kifejezés csak konstansokat, literálokat és beépített operátorokat tartalmazhat (pl.: 6*(4+c) ). A konstans típusát nem kell explicit módon megadni, mivel az egyenlőség jobb oldala alapján egyértelműen meghatározható.

Az említetteken kívül a CLU nyelv megenged ún. típus-konstansokat is (pl.: ai = array [ int ] ). A típus-konstansok a definiáló típus helyett használhatók (az x : ai és az x : array [ int ] deklarációk ekvivalensek). A konstansdeklaráció jobb oldala nem hivatkozhat sem közvetlenül sem közvetve a jobboldalon definiált típusra. Ilyen módon nem írhatók le rekurzív típusok, tehát ezekhez nem lehet típuskonstanst definiálni.
 

2.3.2. Hatáskörök

Minden törzs új hatáskört definiál, ahol lokális konstansok és változók deklarálhatók.

Változódeklarációt a törzsön belül bárhol, elhelyezhetünk. A definiált változó hatásköre közvetlenül a deklarálása után kezdődik és a deklarációt tartalmazó törzs végéig tart. A konstansokat definiáló egyenlőségeket a törzs elején kell elhelyezni.

Mivel a törzsek egymásba ágyazhatók, a hatáskörök is egymásba ágyazhatók. Viszont a belső hatáskörben nem definiálhatók át a külső hatáskörben definiált azonosítók.
 

2.4. Kifejezések

Minden kifejezés az objektum-univerzum egy objektumává értékelődik ki. A legegyszerűbb kifejezések a változók, a konstansok és a literálok. Ez a forma közvetlenül megadja a hozzájuk tartozó univerzumbeli objektumot. Bonyolultabb kifejezés adódik az eljáráshívásból. Az ilyen kifejezések értéke a legkülső hívás által visszaadott érték.

Más nyelvekhez hasonlóan a CLU-banis használhatók az aritmetikai, összehasonlító operátorok, a tömbindexelés, és a rekordok mezőszelekciója, ezek azonban csak az eljáráshívások rövidített formái.

Sajátosság, hogy a típusban definiált eljárásokat mindig típus-eljárása formában kell megadni.(pl.t$proc(...) -  t a típus neve, proc az eljárásé). A kód olvasahatósága kedvéért, bevezették a szintaktikus cukor fogalmát. Ez lehetővé teszi, hogy a hagyományos algebrai kifejezéseket a megszokott formában adjuk meg: pl. a + b. Az ilyen kifejezéseket egy előfordító a szintaktikai ellenőrző számára megkövetelt fomába alakítja ("cukortalanítja", desugaring) , és a fordítást azon végzi el. A cukoratalanítás során nincs típusellenőrzés, de ha az adott típusnak nincs megfelelő alakú függvénye, akkor a fordító hibát jelez.

          A "cukorkák" a prioritás sorrendjében:

               6: (, ), ~, -,                                           ~ a logikai nem, - a negatív előjel
               5: **,
               4: //, /, *,
               3: ||, +, -,
               2: <, <=, =, >=, >, ~<, ~<=, ~=, ~>=, ~>,
               1: &, cand,
               0: |, cor

Példák:

3+2
int$add( 3, 2 )
b : bool := (i=j)
b : bool := int$equal( i, j )
x : int := a[i]
x : int := array[int]$fetch( a, i )
a[i] := x
array[int]$store( a, i, x )
A kétargumentumos operátorok esetén az általános szabály a következő:
argl op arg2  <--  T$opname( argl, arg2 )
ahol T az arg1 típusa és opname az op művelethez tartozó eljárás neve. A szintaktikai kötetlenségek nem csak a beépített, hanem a programozó által definiált típusokra is használhatók.

A CLU rendelkezik a 'cand' és a 'cor' logikai operátorokkal, amelyek viszont sem rövidítésként sem szintaktikailag nem feleltethetők meg eljárásoknak. Hasonlóak a '&' és a '|' logikai operátorokhoz, de a második argumentumuk csak abban az esetben értékelődik ki, ha szükséges. Hasznosak a futási hibák megelőzésére:

i <= ai$low( a ) cand i <= ai$high( a ) cand ai[ i ] = x

2.5. Értékadás

Az értékadás operátora a : = .
a := b
a := <kifejezés>
Ha a és b mutable típusok, akkor cím szerinti értékadás történik, a második esetben a kifejezés kiértékelődik, létrejön egy objektum ezzel az értékkel, majd a hivatkozását ráállítja. Az a változó korábbi hivatkozása elveszik, ha az objektumra, amire a korábban mutatott már nincs másik hivatkozás, akkor az egész objektum elveszik a program számára. (A szemétgyűjtő fogja kitörölni.)
 

Ha a és b immutable objektumok, akkor érték szerinti értékadás történik. A második esetben nem jön létre új objektum. Az a változó korábbi értéke felülíródik.

A CLU támogatja a szimultán értékadást is, melyben tetszőleges sok változó szerepelhet az egyenlőség bal oldalán.

a, x := b, y
x, y := y, x
Az első eset az a := b és x := y értékadásoknak felel meg, a második esetben x és y értéke felcserélődik.

Egy függvény adhat vissza több értéket, de ezeket csak a szimultán értékadás tudja fogadni, azaz nem szerepelhet          aktuális paraméterként. További megszorítás, hogy ha egy szimultán értékadás jobb oldalán többértékű függvény szerepel, akkor más kifejezés nem állhat a jobb oldalon, s a baloldalon pontosan annyi változó-kifejezésnek kell szereplni, mint a függvény visszatérési értékeinek száma.

2.6. Eljáráshívás

<procedure name> [ generic params] ( <formal params> )
Amennyiben az eljárásnak nincsenek formális paraméterei, akkor is ki kell rakni egy üres zárójel-párt. Ha nincs generikusság, a szögletes zárójel elhagyható.