Az SR programozási nyelv

Típusok, típuskonstrukciók

A legtöbb programozási nyelvhez hasonlóan az SR-ben is megkülönböztetünk előre definiált alaptípusokat és a felhasználó által ezekből ill. más, már bevezetett típusokból felépített típusokat. Más felosztásban lesznek olyanok, melyeken értelmezve van valamilyen ekvivalencia reláció, másokon pedig még valamilyen rendezési reláció is. Először vizsgáljuk meg az alaptípusokat!

Elemi típusok

Az SR-ben öt alaptípus van: bool, int, real, char és a string.

Bool, avagy a logikai típus

Két lehetséges értéke van: true és a false.
Négyféle előre definiált logikai operátor áll rendelkezésünkre:

Amint a fenti listából is látszik, majdnem minden logikai operátor rendelkezik egy egyszerűbb alakkal is. Az első három infix, míg a negáció prefix alakban használatos. Mindegyikük LUSTA kiértékelést használ.

Int típus

Előjeles egész típus.
Operátorai:

Real típus

Lebegőpontos valós típus.
Operátorai:

Char típus

Karakter típus

String típus

Karaktersorozat típus.

Változódeklarációnál meg kell adni a maximális méretét is, pl.:

#20 karakter hosszú string var s : string[20]

Operátorai:

Ezen kívül van két előre definiált függvénye:

Alaptípusokon értelmezett relációk

Minden alaptípus rendezett és értelmezett rajtuk az egyenlőségvizsgálat. String esetén a rendezettség lexikografikus rendezettséget jelent, míg logikai esetben false > true -ként értelmezett. A következő relációs operátorok használhatóak:

=, !=, <, >, <=, >=

Ezek az operátorok a rendezett felhasználói típusokra, míg az egyenlőségvizsgálat a pointerekre és a capabilty-kre is értelmezettek.

A relációs operátorok precedenciája nagyobb, mint a logikai operátoroké.

Típuskonstrukciók

A következő típuskonstrunkciók megengedettek: tömb-, felsorolási-, rekord-, unió-,pointer-, operációtípus ill. operáció capability. Mielőtt megnéznénk mit is jelentenek ezek, ismerjük meg a típusdeklaráció általános szintaxisát:

type type_id = type_definition

Most pedig lássuk a lehetséges típusdefiníciókat!

Felsorolási típus

A felsorolási típusok szimbolikus literálokat definiálnak. Minden felsorolási típus rendezett típus, méghozzá elemeik felsorolásának sorrendjében. Definíciója nem más, mint elemeinek - azonosítóknak, amik a típusértéket reprezentálják - vesszővel elválasztott felsorolása.

enum (id, id, ...)

Nézzünk egy-két példát:

type color = enum (red, green, blue) type countries = enum (UK, HU, RU, FI, ES)

Fontos, hogy a felsorolásban használt azonosítók a teljes programban egyediek legyenek! Ez a korlátozás nem engedi meg, a felsorolási típusértékek átlapolását. Azaz a következő kód hibás:

type viragok = enum (Tulipan, Ibolya, Narcisz, Petunia) type nevek = enum (Kata, Janos, Ibolya, Petra, Euthanazia) # Fordítási hiba

Láthatjuk, hogy ekkor az Ibolya mind a két felsorolásban szerepel, ez fordítási hibához vezetne! (De ha pl. a virágokban kisbetűvel írnánk, az már jó lenne!).

Tömb típus

A tömb definíció szintaxisa a következő:

[range1, range2, ...] type_id

A type_id tetszőleges típusnév. Tehát egy vagy több range, indextartomány vesszővel elválasztva (minden range egy dimenziót reprezentál), ahol egy range-t két féleképp adhatunk meg:

Fontos megjegyezni, hogy mind karakterekkel, mind felsorolási-típusokkal is indexelhetünk tömböket. Nézzünk erre néhány példát:

# Ez igazából nem is tömb(0-dim.) Egyszerű átnevezés. type age = int # 1-től 3-ig indexelt 1 dim. side-ok tömbje type side = real type box = [3] side # Egyszerű átnevezés. A name egy 20 hosszú string lesz. type name = string[20] # 1 dim. egészek tömbje type point = [2] int # 1dim, 0-100-ig indexelt tömb type score_array = [0:100] int # 800x600-as 2-dim. tömb type picture = [1:800,600] int # név, város, utca type address = [3] string[40] # 10x10-es mátrix type real_matrix = [10,10] real

Ezután vizsgáljuk meg, milyen tömb-konstruktoraink vannak, azaz hogyan adhatunk egy tömbváltozónak kezdeti értéket. Ez lényegében a tömb elemeinek vesszővel elválasztott felsorolását ill. az egész bezárójelezését jelenti. Formálisan:

( vect_elem, vect_elem, ... )

ahol minden vect_elem kétféle lehet:

Néhány példa:

(0,0,0) #ekvivalens ([3] 0) (1,2,0,0,0,6) #ekvivalens (1,2,[3] 0,6) ("smith",[2] "jones") #ekvivalens ("smith", "jones", "jones")

A több dimenziós eset teljesen analóg az előzővel. A különbség annyi, hogy ekkor a fenti "kifejezés" mindenhol egy tömb konstruktor.

#10x10-es nullmátrix ([10] ([10] 0.0)) ([5] ([10] 0.0), [5]([10] 1.0))

Megjegyzés: lehetséges típus nélküli tömbdeklaráció is. Ezt részletesebben a változódeklarációknál mutatjuk be.

Rekord típus

A módszertanból ismert direktszorzat típust a legtöbb nyelv rekord segítségével valósítja meg. Ez alól az SR sem kivétel. Nézzük a rekord-definíció szintaxisát:

rec ( fieldname1 : type_id1; fieldname2 : type_id2; ... )

A rekord minden mezőjének méretét már fordítási időben ismernünk kell. (pl. tömb vagy string mezők hossza fordítási idejű konstans kell legyen!)
Rekord-konstruktorokat használhatunk teljes rekord értékének megadásához (hasonlóan a tömbökhöz). Ekkor meg kell adnunk egy azonosítót, a rekord típusnevét, majd zárójelek között egy vagy több kifejezést (vesszővel elválasztva), melyek a rekord mezőinek megfelelő értékek lesznek.

Nézzünk egy két példát a típusmegadásra:

type dims = rec ( width,height : real ) type entry = rec ( width : int; height : real; next : ptr entry ) type person = rec ( name : string[10]; grade : int ) type info = rec ( p : person; m : dims; employed : bool )

Példák a rekord-konstruktorokra:

dims( 3.8, 2.1 ) person( "Xerediné", 92 ) info( person("Smith", 11), dims(7.3, 2.9), false )

Unió típus

Az unió típus különböző típusok gyüjteménye, melyek mindegyike rendelkezik egy hivatkozási névvel. Az SR a C nyelvben megismert szabad uniót valósítja meg. A rekordhoz hasonló szintaxissal definiálható:

union ( fieldname1 : type_id1; fieldname2 : type_id2; ... )

A rekorddal ellenben egyszerre csak egy mező hordozhat korrekt adatokat. A C-nél látott problémák itt is fennállnak. Csak nagy odafigyeléssel használjuk.

Lássunk egy-két példát:

# Mindkettő ugyanzt az adatot nyújtja type circle = union ( radius, circumference : real ) type uperson = union ( name : string[10]; ID : int )

Csak valamely mezőjén keresztűl kaphat értéket!

Pointer típus

Különböző adatokra mutató referenciákat definiál a pointer típus. Lehetőségünk van típushoz kötött és típusfüggetlen pointer típusok definiálására.

ptr type ptr any

Az első típusú pointer csak az adott típus objektumaira állítható, míg a második bármilyen típus példányára.

Nézzünk példákat:

# int-re pointer type pint = ptr int # int pointer-re pointer type ppint = ptr ptr int # ugyanz, mint az előző type pp2int = ptr pint type prec = ptr rec(i1,i2 : int) type pany = ptr any # int-re pointer type p42int = ptr [42] int

Az általánosított ptr any pointer típus bármilyen más típusú objektumra hivatkozhat, értékül adható másik ilyen pointernek. De nem lehet dereferálni!
A null pointer literál használható üres referenciaként. Ez bármely pointer típus esetén használható.
Az address-of operátor az @ karakter, ami visszaadja egy változó címét, mely bármely (megfelelő típusú) pointernek értékűl adható.

Változók és konstansok

Változódeklarációk általános formája a következő:

var var_def, var_def, ... ,ahol var_def ::= varname1{,varname2} : type [:= value]

Tömbök esetén a változónevek után []-jelek között dimenziókat is megadhatunk.(Névtelen tömb típus)

Látható, hogy a változódeklarációkat a sor eleji var kulcsszó vezeti be. Lehetőségünk van kezdeti érték megadására is. Tömbök és rekordok esetén a korábban bemutatott konstruktorokkal adhatunk kezdeti értéket.

Példák:

var i, j, k : int var fr := 1, js, ka := 23 : int var i : int, j : real, k : int var i[12], j[80], k : string[23] var mx[10,10] : int

A konstansok bevezetése a változódeklarációtól (szintaxisában) teljesen függetlenül történik. Konstansokat a sor eleji const kulcsszóval vezetjük be.

const const_name = value

Operátorok

A := értékadó operátor egy váltózónak (pontosabban balértéknek) egy kifejezést ad értékűl. Maga az operátor NEM kifejezés, azaz az SR ebben a Pascalos vonalat követi.

Értékadás formája:

variable := expression

Ezenkívűl számos összetett, speciális értékadásra is lehetőségünk van. Ezek az operátorok a C értékadó operátoraihoz hasonlóak:

Ezen operátorok jelentése: a bal oldal és jobb oldal között a := előtti műveletet elvégezzük, és az eredményt értékűl adjuk a bal oldalon álló változónak (pl.: a +:= b <===> a := a + b).
A |:= és a &:= operátorok logikai változók és kifejezések között, míg a ||:= a konkatenáció, stringek között használatos.
A >>:=, <<:= pedig a jobbra- ill. balrashiftelés bitműveletei.
Ezeken kívűl működik még a C-ben használatos pre-, ill. postfix ++ , és --, ami a módszertanbeli increase és decrease műveleteknek felel meg.
Specialitása a nyelvnek, hogy rendelkezik egy beépített swap/csere operátorral (:=:). Ennek mindkét oldalán balérték kell, hogy szerepeljen. Az operátor végrehajtása után a bal- ill. jobboldalon levő változók értéke megcserélődik, kölcsönösen értékűl adódik a másiknak.

Példa swap operátorra:

var a : int := 10 var b : int := 42 # a=10 és b=42 a :=: b # a=42 és b=10

Típusekvivalencia

Az SR-beli típusekvivalencia a struktúrális ekvivalencián alapul. Egy objektum akkor adható értékűl egy másiknak, ha struktúrájuk azonos.

Nézzük a következőket:

type r1 = rec ( a : real ; b : int ) type r2 = r1 type r3 = rec ( c : real ; d : int ) type r4 = rec ( a : int ; b : real ) type col = enum ( cyan, magenta, yellow ) type names = enum ( pista, jozska, kata ) type books = enum ( thesaurus, dictionary )

Tehát a fentiek alapján az r1 és r2 triviálisan ekvivalens ugyanúgy, ahogy az r1 és r3, ill. az r2 és az r3. Azonban az r1 és r4 nem ekvivalensek, mivel mezőik típusai nem ekvivalensek. Hasonlóan a col és a names felsorolási típusok is ekvivalensek. (A books-szal egyikük sem ekvivalens)