Az OCCAM programozási nyelv

Alprogramok, modulok

Eljárások

OCCAM-ban a procedure definíció egy nevet rendel egy processzhez. Formális definíció:

DEFINITION ::= PROC név (FORMAL*)
       Process :
FORMAL ::= specifier {name} + | VAR specifier {name} +

Pl.:

PROC increment ( INT x )
      x := x + 1
:
INT Y :
SEQ
      ...
      increment (y)
      ...

A formális paraméter egyfajta rövidítése az aktuális paraméternek, amit az eljárás egy példányaként használhatunk. Az eljárás egy példányának ugyanaz a hatása, mint az eljárás definíciójában elnevezett processz helyettesítésének. Az OCCAM eljárásokkal rekurzió nem oldható meg, mivel az eljárás törzsének végéig az eljárás meg nem ismert, nem definiált, így nem lehet rá hivatkozni.

Paraméterátadási módok

A paraméterátadási módok megfelelnek az OCCAM-ban "rövidítés"-nek nevezett változómásolási módszereknek. Lehetőségünk van cím szerint lemásolni egy változót, vagy érték szerint. Érték szerint kifejezésekhez is rendelhetünk értékeket. Pl.:

INT n IS m : -- n változó m új neve lesz
VAL REAL32 y IS (m * n) + c : -- létrejön y REAL32 változó, és felveszi a kifejezés értékét

Ennek megfelelően a paraméterátadás lehetséges érték és cím szerint, attól függően, hogy használom-e a VAL kulcsszót. Pl.:

PROC eljaras (INT x, VAL [] BYTE string)
       ...
eljaras ( i, "Hello")

A paraméter átadásakor sincsen semmilyen implicit típuskonverzió, ezt nekünk kell megtennünk explicit módon a függvényhívás helyén. Pl.:

PROC writefname (CHAN OF BYTE stream, VAL DOSFNAME string) -- függvény deklaráció
writefname (screen, "autoexec.bat"(DOSFNAME)) -- függvényhívás

Három változata van a rövidítésnek paraméter átadása szempontjából:

Érdekesség:

INT step :
   SEQ
       step := 39
       PROC next.item (INT next, VAL INT this)
          next := this + step
          :
       INT g, step :
          SEQ
          step := 7
          next.item (g, 3)
          ... – itt g értéke 42, mivel a step az eljárás definíciója előtt lett definiálva és itt is kapott értéket. Ha mi ezt a step-et egy belső blokkban felüldefinináljuk és ezután hívjuk meg az eljárást, akkor ennek törzsében a külső step lesz látható.

A paraméterátadási szabályok megegyeznek a rövidítési szabályokkal, melyek azt hivatottak biztosítani, hogy a program egy adott pontján egy változóra csak egy név hivatkozzon.

És most határozzuk meg, hogy a következő példák közül melyek ekvivalensek:

next.item (x, y) ekvivalens:
    INT next IS x :
    VAL INT this IS y :
    next := this + step
next.item (x, step) ekvivalens:
    INT next IS x :
    VAL INT this IS step :
    next := this + step
next.item (step, x) ekvivalens:
    INT next IS step : 
    VAL INT this IS x :
    next := this + step ILLEGÁLIS!
next.item (x, x) ekvivalens:
    INT next IS x : 
    VAL INT this IS x :
    next := this + step ILLEGÁLIS!

Itt látható, ahogyan minden egyes eljárás paraméter jelentése, rövidítés közben lett definiálva. A paraméterek rendezése kapcsolódik a rövidítés sorozatához, ez illegális, mert a változók, amiket a kifejezésekben használunk, a rövidítés után összeakadnak. A parameter nélküli eljárásoknál kötelező kitenni az üres zárójeleket. Lehet rövidíteni a paraméterlistát, ha két azonos típusú paraméter kerül egymás után, akkor elég a típus cask egyszer kiírni.

Pl.:

PROC snark (VAL INT butcher, beaver, LENGTH boojum, jubjub)

:

Ekvivalens ezzel:

PROC snark (VAL INT butcher, VAL INT beaver, LENGTH boojum, LENGTH jubjub)

:

Kiértékelt eljárások, függvények

OCCAM-ban a függvények elnevezett elkülönített processzek, melyek valamely eredményt adnak vissza, vagyis kiértékelt eljárások. Példa kiértékelt eljárásra:

total := subtotal + (INT sum :
       VALOF
           SEQ
             sum := 0
             SEQ i = 0 FOR SIZE v
                sum := sum + v[i]
          RESULT sum
)

Függvényként deklarálhatunk kiértékelt éljárásokat, nevet adhatunk vele kifejezéseknek. Pl.:

INT FUNCTION sum (VAL [] INT values)
   INT accumulator :
   VALOF
       SEQ
          accumulator := 0
          SEQ i = 0 FOR SIZE values
             accumulator := accumulator + values[i]
       RESULT accumulator
:

BOOL FUNCTION lowercase ( VAL BYTE ch ) IS ( ch >= 'a' ) AND ( ch <= 'z' ) :

Egy függvény több értékkel is visszatérhet, ezeket használhatjuk pl. többszörös értékadásoknál. Pl.:

point, found := (
    VAL BYTE char IS 'G' :
    VAL []BYTE string IS message :
    BOOL ok :
    INT ptr :
    VALOF
       IF
          IF i = 0 FOR SIZE string
             string[i] = char
                SEQ
                   ok := TRUE
                   ptr := 1
          TRUE
                SEQ
                   ok := FALSE
                   ptr := -1
       RESULT ptr, ok
)

A függvény definíciója áll a FUNCTION kulcsszóból, előtte felsorolva a visszatérő értékek típusai, majd a függvény nevéből, zárójelben a paraméterekből, majd a lokális változók deklarációjából :-tal lezárva. Ezután következik a VALOF kulcsszó, és legalább két szóközzel beljebb kezdve a függvény törzse, amit a RESULT kulcsszó zár és utána a felsorolva a visszatérő értékek felsorolva, vesszővel elválasztva.
A paraméterátadás megfelel a változórövidítéseknek.

Lehetőség van OCCAM–ban rövidített függvénydeklarációra is, ahol nem kell kiírni az egész függvénytörzset, csak a visszatérőértéket. Pl.:

BOOL FUNCTION isletter (VAL BYTE ch) IS uppercase (ch) OR lowercase (ch) :

Ez ekvivalens az alábbival:

BOOL FUNCTION isletter (VAL BYTE ch)
    VALOF
       SKIP
       RESULT uppercase (ch) OR lowercase (ch)
:

Modulok, interface-ek

Lásd a 11.fejezetben .

Könyvtárak

A könyvtárakat hasonlóan használhatjuk, mint a modulokat, csak itt megengedünk nem csak műveletekre, hanem bizonyos adattagokra való hivatkozást is. Pl.: Egy halmaztípus ábrázolása:

EXPORT
    DATA TYPE NAME SET :
    VAL SET empty :
    PROC add (SET set, VAL INT n) :
    BOOL FUNCTION member (VAL SET set, VAL INT n) :
    PROC delete (SET set, VAL INT n) :
FROM
    DATA TYPE SET IS [64]BOOL :
    VAL SET empty IS [ARRAY i = 0 FOR 64 : FALSE] :
    PROC add (SET flags, VAL INT n)
    flags[n] := TRUE
    :
    BOOL FUNCTION member (VAL SET flags, VAL INT n) IS flags[n] :
    PROC delete (SET flags, VAL INT n)
    flags[n] := FALSE
    :
: