Az Argus programozási nyelv

Típusok, típusgenerátorok, típusspecifikációk

A típus tartalmazza objektumok egy halmazát, valamint műveleteket az objektumok manipulálására. A típusokat osztályozhatjuk aszerint, hogy az objektumaik mutable vagy immutable, ill. atomiak vagy nem atomiak. Egy immutable objektum (pl. egy egész) értéke soha nem változik meg, míg egy mutable objektum értéke (állapota) idővel megváltozhat. Az atomic (atomi) típusú objektumok sorolhatóságot és helyreállíthatóságot biztosítanak a hozzáférő akciók számára. A non-atomic (nem atomi) típusok szinkronizációt biztosítanak specifikálva egy partikuláris műveletet, ami oszthatatlanul hajtódik végre a típus egy objektumán. Egy művelet oszthatatlan, ha semmilyen más processz nem lehet hatással a művelet végrehajtása közbeni állapotokra. Az oszthatatlansági tulajdonságok az Argus összes beépített, nem atomi típusára jellemezve lesznek.

A típusgenerátor egy paraméterezett típusdefiníció, amely egy kívánt típusok (legtöbbször véges) halmazát reprezentálja. A pontos típust a generátor típusból úgy kapjuk, hogy a leírjuk a generátor nevét, utána paraméterként a megfelelő értékeket. Például az array típusgenerátor egyetlen paramétere van, amely meghatározza az elemek típusát. Az array[int], array[real], és az array[array[int]] három különböző típus, amelyeket az array típusgenerátor definiál. Azokat a típusokat, amelyeket típusgenerátorból kapunk, paraméterezett típusnak, vagy örökölt típusnak hívjuk, a többit egyszerű típusnak.

Az Argus kódban a típus specifikációjára egy type_spec konstrukció szolgál. A típusspecifikáció egyszerű típus esetén csak a típus megnevezéséből áll, ami egy azonosító vagy foglalt szó. Paraméterezett típus esetében a specifikáció tartalmazza a típusgenerátor nevét (ami szintén egy azonosító vagy foglalt szó) az aktuális paraméter értékével együtt.

Az objektumoknak átvihetőeknek kell lenniük, hogy felhasználhassuk őket handler ill. creator hívások paramétereként és visszatérési értékként, valamint image objektumként. Az Argus legtöbb beépített típusa átvihető, tehát az objektumaik átvihetőek. Az eljárások és az iterátorok sohasem átvihetőek. A típusgenerátor esetében a származtatott típus átvihetősége függ a paraméterek átvihetőségétől. Az átvihető típusoknak van egy transmit pszeudo operátoruk és két beépített művelet encode és decode. Általában ez a két művelet rejtett, és implicit hívódnak meg üzenetváltáskor, ill. image objektumok létrehozásakor, ill. dekomponálásakor.

Az Argus nyelv biztosítja a CLU nyelv összes beépített típusát, valamint néhány új típust és típusgenerátort. Ez a fejezet egy informális leírást tartalmaz az Argus beépített típusairól és típusgenerátorairól.

Típus tartalmazás

A típus tartalmazás fogalma az Argusban más, mint a CLU-ban. Az any típus olyan, mint bármely más típus, de nincs implicit korlátozás az any típusra, tehát nem kell a típus tartalmazás szabályában külön vizsgálni. A típus tartalmazás az Argusban hasonló, mint a típus egyenlőséghez, kivéve az eljárás, iterátor, handler, és creator típusok esetében. A V rutin típus tartalmazza az O rutin típust, ha az argumentumok száma és típusai, valamint a visszatérési értékek száma és típusai megegyeznek, és O minden kivételéhez van V-ben neki megfelelő kivétel, amit azonos számú és típusú értékeket tartalmaz. Megjegyzendő, hogy V-nek lehet több kivétele is, mint O-nak, de ez a szabály nem rekurzív, amikor az argumentumok és eredmények típusát hasonlítjuk össze, típus egyenlőséget használjuk.

p:proctype(real,real) returns(real) signals(overflow,underflow) q:proctype(real,real) returns(real)

Ekkor a p típus tartalmazza q típust, de fordítva ez nem igaz. Így a p:=q értékadás helyes.

Szekvenciális beépített típusok és típusgenerátorok

Ebben a fejezetben bemutatjuk az Argus szekvenciális beépített típusait. Ezek a típusok általában hasonlóak a CLU-beli típusokhoz. Ez a fejezet főleg az új jellemzőkre koncentrál. Az abortált akciók esetén az immutable objektumok helyreállíthatósága triviális, hiszen az abortált akció nem volt hatással ezen objektumokra. A beépített skalár típusok, mint pl. null, bool, int, real, char, és a string típusok immutable, atomi és átvihető típusok. A CLU-ból ismert beépített, mutable típusgenerátorok nem atomiak.

Null

A null típus pontosan egy immutable objektumot jelöl, amelyet a nil literál reprezentál. Ez atomi és átvihető.

Bool

Kétféle immutable bool (logikai) típusú objektum létezik. Az ehhez tartozó literálok a true és a false, amelyek a nevüknek megfelelő logikai értékeket reprezentálják (igaz, hamis). Az equal(=), and(&), és az or(|) bináris, valamint a not(~) unáris műveletek állnak a rendelkezésre. A bool típusú objektumok atomiak és átvihetőek.

Int

Az int (egész) típus a matematikai egészek egy tartománya. A tartomány pontos megjelölése nem része a nyelv definíciójának. Az egészek immutable, atomi és átvihetőek, a hozzájuk tartozó literálok egy vagy több decimális számjegy szekvenciájából állnak. Léteznek oktális és hexadecimális literálok is. Az add(+), sub(-), mul(*), div(/), mod(//), power(**), max, és a min bináris, valamint a minus(-), és az abs unáris operátorok használhatóak. Léteznek még bináris összehasonlító operátorok, ezek az lt(<), le(<=), equal(=), ge(>=), és a gt(>). Két iteráció még a from_to és a from_to_by, amelyek az egészek egy részét állítják elő.

Real

A real (valós) típusok a matematikai valós számok egy részhalmazát reprezentálják. A pontos részhalmaz megjelölése nem része a nyelv definíciójának. A valós számok immutable, atomiak és átvihetőek, bár a real objektumok átvitele heterogén gépek között nem biztos, hogy pontos lesz. A valós literálokat a mantissza és az opcionális exponens rész jelöli. A mantissza egy vagy több decimális számjegy sorozata, vagy két szekvencia (az egyik lehet üres is), amelyet egy pont írásjel választ el egymástól. A mantisszának tartalmaznia kell legalább egy számjegyet. Az exponens egy E vagy e, amelyet egy + vagy egy - jel követhet, plusz még egy vagy több decimális számjegy. Az exponenes rész kötelező, ha a mantissza nem tartalmazza a pont írásjelet. Ahogy megszokhattuk, mEx = m*10x. Néhány példa valós literálra: 3.14 ; 3.14E0 ; 314e-2 ; .0314E+2 ; 3. ; .14.

Mint az egészeknél, itt is az add(+), sub(-), mul(*), div(/), mod(//), power(**), max, min, minus(-), abs, lt(<), le(<=), equal(=), ge(>=), és a gt(>) műveletek használhatóak. Fontos megjegyezni, hogy nincs lehetőség típusok közötti implicit konverzióra. Az i2r művelet használható az egész valóssá történő konvertálásához, az r2i egy valós számot kerekít egésszé, míg a trunc levágja a valós szám törtrészét.

Char

A char (karakter) típus az ábécét biztosít szövegek manipulálásához. A karakterek immutable, atomi, és átvihető típusok, amik rendezett halmazt alakítanak ki. Minden reprezentációnak biztosítani kell legalább 128, de nem több, mint 512 karaktert, és az első 128 karaktert az ASCII szabványnak megfelelő sorrendben. A literálok a nyomtatható karakterekhez (40 oktális számtól a 176 oktális számig), kivéve az egyszeres idézőjel (') és a backslash (\), leírhatók egyszeres idézőjelek(') közé. Használhatóak még a 6.1 ábrán látható escape szekvenciák is. Az escape szekvenciák nagy betűkkel írandóak, de a \&* alakú escape szekvenciák nem különböztetik meg a kis és nagybetűket. Példa karakter literálokra: \7' ; 'a' ; '"' ; '\"' ; '\'' ; '\B' ; '\177'

Két operátor létezik az egészek és a karakterek közötti konverzióra, ezek az i2c és a c2i. A legkisebb karakter megfelel a nullának, és a karakterek szekvenciálisan sorszámozottak. Bináris összehasonlító operátorok léteznek, amik ezen a numerikus sorszámozáson alapulnak: lt(<), le(<=), equal(=), ge(>=), és a gt(>).

Escape szekvenciaKarakter
\'' (egyszeres idézőjel)
\" " (idézőjel)
\\ \
\n NL (újsor)
\t HT (vízszintes tabulátor)
\p FF (új oldal)
\b BS (backspace)
\r CR (kocsivissza)
\v VT (függőleges tabulátor)
\*** oktális szám (pontosan 3 jegyű)
\#** hexadecimális szám (pontosan 2 jegyű)
\^* 0-31 -ig számozott karakterek (* nyomtatható karakter)
\!* 128-159 -ig számozott karakterek (* nyomtatható karakter)
\&* 160-255 -ig számozott karakterek (* nyomtatható karakter)

String

A string típus a szövegek reprezentálására szolgál. A string immutable,atomi és átvihető sorozata 0 vagy több karakternek.A stringek lexikografikusan rendezettek,és a karakterek rendezettségén alapul ezen rendezés. Egy string literál nulla vagy több karakterből és escape szekvenciából áll, melyeket dupla idézőjelek (") közé teszünk. "

A string karakterei sor rendbe vannak helyezve, az 1-es indextől kezdve. A fetch mávelet szolgál a string bizonyos indexű karakterének lekérdezésére. A substr a string egy rész-string-ét adja vissza. A string végének lekérdezésére a tail szolgál. A stringekben való keresésre az indexc és indexs fűggvényeket használhatjuk.

Két stringet össze is fűzhetünk a concat (||) művelettel, valamint egy darab karakterrel megtoldhatjuk a stringünket az append művelet segítségével. Egy darab karaktert sztringé konvertálhatunk a c2s művelettel. A size a sztring méretét adja meg. Chars egy iterrátor, mely a string karakterein halad végig az elejétől a végéig. Az egyes összehasonlító műveletek a lexikografikus rednezéshez itt is rendelkezésünkre állnak (lt,le,gt,ge).

Any

Az any típus objektumai tetszőleges típusú objektumot tartalmazhatnak,és ezáltal kibújhatunk a fordítás időbeli típusellenőrzés alól. Eltérően a CLU-tól ahol az any típus teljesen elkülönített a többi típustól,az Argusban az any egy normális típus. Ezért van neki egy explicit create eljárás generátora, valamint a force is egy művelet-generátora az any típusnak.Egy any típusrú objektumra úgy gondolhatunk mint ami tartalmaz egy objektumot és annak típusát is. Mivel nincs olyen operátora az any típusnak ami ennek állapotát megváltoztatná az any objektumait immutablenek tekinthetjük. Mindazonáltal a tartalmazott objektum állapota változhat, ha az egy megosztott objektum, így ezen szembszögből nézve az adott objektum mutabilitása és atomicitása a tartalmazott objektum mutalitásától és atomicitásától függ. Az any típusú objektumok nem átvihetőek.

A create művelete típussal paraméterezhető: a create egy paramétert kap az adott típussal, és egy any objektumot ad vissza mely az argumentumot tartalmazni fogja. A force művelet szintén egy típussal paraméterezendő,mely után a az any objektumból egy a paraméterként kapott típusú objektumot ad eredményül: wrong_type signált jelez ha a paraméter típusában nincs benne a tartalmazott objektum típusa. Az is_type fűggvénnyel ellenőrizhetjük azt hogy a tartalmazott objektum típusa a paraméterként kapott megegyező-e vagy sem. A részletes specifikációt az II.19 ben találhatjuk meg.

Szekvencia típusok

A szekvenciák immutable-k, és attól függően hogy milyen típussal példányosítjuk ahhoz képest atomi vagy nem atomi típusúak lesznek. Habár egy szekvenciának tetszőleges mérete lehet, azonban miután a szekvenciát létrehozuk annak mérete már nem változhat. A szekvencia elemei sorszámozva vannak az egyes sorszámtól kezdve. A szekvencia típus specifikáció formája a következő alakú: sequance[type actual] ahol a paraméter egy típus-specifikáció,lehetőség van operátor kötésre.

A new operátor egy üres szekvenciát ad vissza. A szekvencia konstruktor a következő alakú: type_spec [[kifejezés..]] és a megadott argumentumokkal hozza létre az adott szekvenciát. Noha a szekvenciát miután létrehozuk nem tudjuk megváltosztatni, új szekvenciákat létrehozhatunk a régiekből az addh,addl,remh,reml operátorok segítségével. Más operátorok mint a fetch,replace,top,botton,size és az elements valamint az indexes iterátorok és a subseq. A fetch műveletet a következő speciális formában is használhatjuk: c[i] %a c sor i. eleme

Két szekvencia azonos ha elemeik megegyeznek. Az = operátor azt teszteli hogy két sornak azonosak e az elemei. A similar operáció pedig azt ellenőrzi, hogy az elemek a rajtuk értelmezett similar müveletre megegyeznek-e. Minden művelet oszthatatlan, kivéve a fill_copy, equal, similar, copy, encode decode melyek a paraméterek műveleteinek hívásánál oszthatóak. A részletes specifikáció a II.8 részben található meg.

Tömb típusok

A tömbök egy dimenziósak,mutable és nem atomiak. Csak akkor átvihetőek, ha a parméterének típusa átvihető. A tömb elemeinek száma változhat dinamikusan. Nincs külön jelzés az inicializálatlan elemekre. Egy tömb állapota tartalmaz egy egész értéket melyet az alsó küszöbértéknek nevezünk(low bound), valamint objektumok egy sorozatát mely az elemeket tar talmazza. A tömb elemei sorba vannak rendezve az indexik által, az alsó korláttól kezdvődően. Minden elemnek azonos típusúnak kell lennie. Ez a típus a tömb típusspecifikációjában adható meg,melynek formája a következő: array[type_actual]

Több lehetőségünk is van tömbök létrehozására,melyek közül most csak kettőt említünk meg itt. A create művelet egy egész számot vár paraméterül, és létrehoz egy üres vermet melynek elemei ezen indextől kezdve vannak indexelve. Másik lehetőségként létrehozhatunk egy vermet úgy is, hogy annak elemit inicializáljuk a konstruktor segítségével.

array[int]$[5:1,2,3,4]

Ezen utasítás egy 4 elemű vermet hoz létre melynek első eleme az 5-ös indexű, és értéke 1.

Vagy az array[bool]$[false,true] egy 2 elemű tömböt hoz létre melynek alsó indexe a default értéka azaz 1.

Egy tömb specifikációja nem mond semmit annak szélső indexeiről. Ez azért van így mivel a tömb mérete dinamukusan növekedhet illetve csökkenhet, az addh, addl,remh,reml műveletek használatával. A tömb egyéb műveletei a fetch,strore, top,bottom,high,low valamint az elements és indexes iterrátorok, valamint a size függvény.

A fetch és store műveletek a következő formában is írhatóak: a[i] %az a tömb i-ik elemét szolgáltatja a[i]:=3 %az a tömb i. elemének a 3 -at adja értékül.

Minden újonan létrehozott tömb különbözik az összes többi más tömbtől. Két tömbnek lehetnek ugyanazon elemeik miközben a két tömb nem ugyanaz az objektum. Két tömb objektum megkülönböztetésére az = operátor szolgál. A similar1 művelet megállapítja az elemekre érvényes egyenlőség művelet segítségével, hogy a tömböknek ugyanazok-e az elemei. A similar operáció pedig azt teszteli az elemek similar műveletével, hogy a két tömbnk hasonló e az állapota.

Minden művelet oszthatatlan,kivéve a fill_copy,similar1,similar,copy,encode és decode műveleteket melyek megosztthatóak az argumentumok műveleteinek hivásakor. Részletes információk a II.9 részben.

Struktúra típusok

Egy struktúra típust egy struktúra konstrukor segítségével hozunk létre. Például ha azt mondjuk, hogy az info nevű struktúra legyen a következő:

info = struct[last,first,middle : string,age:int]

akkor ezt konstrukor segítségével a következő módon tehetjük meg:

info& {last: 'Kiss',first : 'Attila',age :32, middle :'W.')

Minden szelektornak egy kifejezést kell megadnunk,de az egyes szelektorok sorrendjének és csoportosításának nem kell megegyezni a típus specifikációjában levővel. Minden "sel" nevű szelektor esetében rendelkezésünkre áll egy get_sel művelet valamint egy replace_sel művelet a szelektor értékének megállapítására illetve módosítására,mely utóbbi művelet során egy új típus jön létre a már megváltoztatott értékekkel. A get műveletet rövidíthetjük egy speciális formával is: st.age % az st nevű struktúrának az age szelektorhoz tartozó értéke.

Mint ahogy a szekvenciák esetében is két structure megegyezik ha elemeik is megegyeznek. Két structure egyenlőségét teszteli az =(equal) operátor, és igaz értéket ad ha a két struktúrának azonos komopnensei vannak. (a komponensek egyenlőség operátora alapján)A similar művelet a komponensek similar művelete segítségével állapítja meg hogy a két struktúra hasonló.

Minden művelet oszthatatlan,kivéve a equal,similar,copy,encode és decode műveleteket melyek megosztthatóak az argumentumok műveleteinek hivásakor.

Rekord típusok

Egy rekord egy vagy több nevesített objektum mutable kollekciója. A rekord sohasem atomi, és csak akkor átvihető ha minden egyes paraméter típusa átvihető. A rekord típus specifikációjának formája a következő:

record [ mező_specifikáció, ... ]

ahol pedig (akárcsak a struktúrák esetén)

mező_specifikáció ::= név, ... : aktuális_típus

Egy specifikáción belül a szelektoroknak egyedieknek kell lenniük, de a szelektorok sorrendje és csoportosítása nem lényeges.

Egy rekord objektum létrehozása a rekord konstruktor használatával történik.

professzor${vezetéknev: "Herlihy", keresztnev: "Maurice", kor: "32" }

Minden egyes "sel" szelektorhoz létezik egy get_sel művelet a megnevezett komponens kinyeréséhez, és egy set_sel művelet a megnevezett komponens egy másik objektummal való helyettesítéséhez. Ezeknek a műveleteknek a meghívása egy speciális formában is megadható:

r.vezeteknev % az r 'vezeteknev' komponensenek kinyerése r.kor := 33 % az r objektum 'kor' komponensét állítja be (set_age meghívásával)

Akárcsak a tömbök esetén, minden újonnan létrehozott rekord egy egyedi identitással rendelkezik; két rekordnak lehetnek ugyanazok a komponensei anélkül, hogy ugyanazt a rekord objektumot határoznák meg. A rekordok identitásai között az equal(=) művelettel lehet különbséget tenni. A similar1 művelet teszteli, hogy a két rekordnak ugyanazok-e a komponensei, az összehasonlításhoz az equal műveletet felhasználva. A similar> művelet teszteli, hogy két rekordnak hasonlóak-e a műveletei, a komponens típusok similar műveletét felhasználva.

Minden művelet oszthatatlan, kivéve a similar, similar1, copy, encode és decode műveleteket, ezek oszthatók a típus paraméterek műveleteinek meghívásakor.

Oneof (unió) típusok

Egy oneof típus egy cimkézett, diszkriminánsos unió típusnak felel meg. Egy oneof objektum egy megjelölt immutable objektum, alternatívák adott halmazának egy elemeként foghatjuk fel. A jelölést cimkének, az objektumot értéknek hívjuk.

oneof [ mező_specifikáció, ... ] %ahol (akárcsak a struktúráknál): %mező_specifikáció ::= név, ... : aktuális_típus

Az egy specifikáción belüli cimkéknek egyedieknek kell lenniük, de sorrendjük és csoportosításuk nem lényeges. Egy példány akkor és csak akkor lesz atomi vagy átvihető ha minden típus paramétere atomi vagy átmeneti.

Egy oneof típus minden egyes "t" cimkéjéhez létrejön egy make_t művelet, amelynek paramétere egy a cimkének megfelelő objektum, és az objektumot a "t" cimkével jelölt oneof objektummá alakítja.

Egy oneof objektum cimkéjének és értékének megállapításához a tagcase utasítás használható.

Az equal(=) művelet teszteli, hogy a két oneof objektum cimkéje megegyezik-e, és ha igen, akkor a két komponens egyenlő-e, utóbbihoz a komponens típusának equal műveletét használja. A similar művelet teszteli, hogy két oneof objektumnak a cimkéje megegyezik-e, és ha igen, akkor a komponensek hasonlóak-e, utóbbihoz a komponens típusának similar műveletet használja.

Minden művelet oszthatatlan, kivéve az equal, similar, similar1, copy, encode és decode műveleteket, amelyek a típus paraméterek műveleteinek hívásakor oszthatók.

Variáns típusok

Egy variáns tulajdonképpen egy mutable oneof típus. A variáns típus sohasem atomi és akkor és csak akkor átvihető, ha minden típus paramétere átvihető. Egy variáns típus specifikációja: variant [ mező_specifikáció ] ahol (akárcsak a oneof esetében) mező_specifikáció ::= név, ... : aktuális_típus

Egy variáns objektum állapotát egy rendezett pár írja le, amely egy cimkéből és egy objektumból áll, utóbbi neve érték. Egy variáns típus minden egy "t" cimkéjéhez létezik egy make_t művelet, amelynek paramétere egy a "t" cimkének megfelelő objektum, és ezt a "t" cimkével ellátott variáns típussá alakítja. Ezen kívül létezik egy change_t művelet is, amelynek paramétere egy a "t" cimkének megfelelő objektum, és a variáns állapotát változtatja meg, az új állapotban a cimke "t", az érték pedig a megadott objektum lesz. Egy variáns objektum cimkéjének és értékének a megállapításához általában a tagcase utasítást használjuk.

Minden egyes újonnan létrehozott variáns objektum különbözik mindegyik másik variáns objektumtól; két variáns állapota lehet ugyanaz, anékül hogy ugyanazt az objektumot jelentenék. A variánsok identitását az equal művelettel különböztethetjük meg. A similar1 művelet teszteli, hogy két variánsnak ugyanaz-e a cimkéje, és ha igen, akkor az érték komponensek megegyeznek-e, utóbbihoz az érték típusának equal műveletét használja. A similar művelet teszteli, hogy a két variáns objektumnak ugyanaz-e a cimkéje, és ha igen, akkor az érték komponensek hasonlóak-e, utóbbihoz az érték típusának similar műveletét használja.

Mindegyik művelet oszthatatlan, kivéve a similar, similar1, copy, encode és decode műveleteket, amelyek a típus paraméterek műveleteinek meghívásakor oszthatók.

Eljárás és iterátor típusok

Eljárás és iterátor objektumokat az Argus rendszerben megismert módon vagy a bind kifejezéssel hozhatunk létre. Nem átvihető típusok. Mivel egy eljárás vagy iterátor objektum imuutable, ezért atominak tekinthető. Azonban az atomiságot tönkreteheti, ha az eljáráshoz vagy iterátorhoz saját adatok tartoznak, és így az eljárásnak/iterátornak mutable az állapota. Egy saját adatokat tartalmazó eljárás vagy iterátor immutable volta és atomisága a műveletek szemantikáján múlik.

Egy eljárás vagy iterátor típus specifikációja az eljárás vagy iterátor fejlécében megadandó információ nagy részét tartalmazza:

proctype ( [ típus_specifikáció, ... ] ) [ returns ] [ signals ] %és egy iterátor típus specifikációjának formája: itertype ( [ típus_specifikáció, ... ] ) [ yields ] [ signals ] %ahol % returns ::= returns (típus_specifikáció, ...) % yields ::= yields (típus_specifikáció, ...) % signals ::= signals (kivétel, ...) % kivétel ::= név [ (típus_specifikáció, ...) ]

Az első típus specifikáció lista az argumentumok számát, típusát és sorrendjét írja le. A returns vagy yields klózok a visszaadott objektumok számát, típusát és sorrendjét adja meg. A signals klóz az eljárás vagy iterátor által kiváltott kivételek listáját adja meg; minden kivétel esetén annak a nevét, típusát és a visszaadott objektumait is megadjuk. Minden egyes a signals klózban szereplő névnek egyedinek kell lennie. A kivételek megadásának sorrendje nem lényeges.

Az eljárás és iterátor típusoknak van equal(=) művelete. Az eljárás meghívása nem művelet hanem primitív az Argusban.

Atomic_array, Atomic_record, és Atomic_Variant

Az Argus CLU-ból öröklött típusainak áttekintése után lássuk az Argus új típusait. Az Argus kölcsönösen atomi típusgenerátorai a következők: atomic_array, atomic_record és atomic_variant. Az ezekkel a generátorokkal képzett típusok ugyanazokkal a műveletekkel rendelkeznek, mint az analóg, array, record és variant generátorokkal készített típusok, de szinkronizációs és helyreállítási tulajdonságaik különböznek. Mindegyik atomi generátor és a nem atomi megfelelője közötti konverzióhoz létezik egy operátor (például atomic_array[t]$aa2a egy atomi tömböt egy nem atomi tömbbé konvertál).

Egy atomi típusgenerátor műveleteit két csoportba -- olvasó és író oszthatjuk aszerint csak megvizsgálja, vagy módosítja is principális argumentumát -- azaz az operáció típusának megfelelő argumentumot vagy visszatérési értéket. (A bináris műveletek, például ar_gets_ar, esetén a besoroláskor mindkét argumentumot figyelembe vesszük.) Nem meglepően, egy olvasó művelet csak megvizsgálja (olvassa) a principális argumentumát, míg egy író módosítja (írja) is azt. Az atomi típusú objektumokat létrehozó műveleteket az olvasók közé soroljuk. Az író/olvasó kízárás zárolással történik: az olvasók olvasási zárat, az írók írási zárat igényelnek.

Ha a típus paraméterek közül egy vagy több nem atomi típusú, akkor a kapott típus sem atomi mert a komponens objektumok módosításai nem vezéreltek. Az írási/olvasási zárolás viszont ekkor megtörténik, a fentiek szerint. Azaz egy atomi típusgenerátor nem atomi típussal történő példányosítása az atomi típusok többletköltségeivel jár, de semmilyen haszonnal nem szolgál; egy ilyen példányosítás valószínúleg nem adja a probléma helyet megoldását. Az atomi típusgenerátorok csak akkor adnak átvihető típusokat, ha a típus paraméterek is rendre átvihetőek.

Minden egyes atomi típusgenerátor speciális műveletekkel rendelkezik az író/olvasó zárolásokkal kapcsolatos zárak vizsgáltatához és manipulálásához. Ezek a műveletek hasznosak felhasználó által definiált atomi típusok létrehozásakor. A tagtest és tagwait utasítások az atomic_variant típusok számára további struktúrált támogatást nyújtanak. A can_read, can_write, test_and_read és test_and_write műveletekkel a zárolási információhoz relatíve struktúrálatlan módon férhetünk hozzá.

Normális terminálást feltételezve az alábbi műveletek igényelnek olvasási zárat a principális objektumukra vagy az éppen létrehozott objektumra:

atomic_array:

atomic_record:

atomic_variant:

A similar és similar1 műveletek mindkét argumentumokra olvasási zárolást kérnek. A copy és copy1 műveletek a visszaadott értékre is, és a principális argumentumukra is kérnek olvasási zárolást. A test_and_read művelet akkor számót olvasónak ha true értékkel tér vissza; különben sem az írók, sem az olvasót közé nem tartozik.

Normális terminálást feltételezve az alábbi műveletek igényelnek írási zárolást a principális argumentumukra:

atomic_array:

atomic_record:

atomic_variant:

Az equal, can_read és can_write műveletek sem az írók, sem az olvasók csoportjába nem tartoznak.

Ha az atomic_array egy művelete kivétellel terminál, akkor principális argumentumát sohasem módosítjuk; jóllehet a fenti író műveletek még a principális argumentumhoz való hozzáférés előtt írási zárolást kapnak, így előfordulhatnak esetek, amikor kapnak írási zárolást és csak olvassák, de nem módosítják a principális argumentumukat. Például, az atomic_array[t]$trim művelet írónak számít ha a bounds kivétel váltódik ki. Másfelől, ha egy atomic_array művelet érvénytelen argumentum miatt vált ki kivételt, akkor nem kerül sor zárolásra. Például, ha az atomic_array[t]$trim> művelet a negative_size kivételt váltja ki, akkor sem írónak, sem olvasónak nem számít, hiszen a tömb állapotát sem nem olvasta, sem nem változtatta meg (csak az egész argumentumot vizsgálta meg).