A Fortress programozási nyelv

Utasítások, vezérlési szerkezetek

Programstruktúra

A Fortress-programok komponensekre vannak osztva. Minden forrásfájl egyetlen egy komponenst tartalmazhat.
Az "API" mint fogalom, beépített nyelvi elemnek minősűl. Vannak beépített APIk, és mi is irhatunk sajátokat.
Minden komponens deklarálhatja az általa megvalósított APIkat, illetve APIfüggőségeit.

api Executable run(args:String...):() end
Ez az API egyetlen egy függvényt, a run -t deklarálja, aminek a típusa (String...)->().
Ez egy nyíl-típus (lásd késöbb). A () az üres típus ("void" -nak ejtjük).

A Hello World így néz ki Fortressben:
component HelloWorld export Executable run(args) = print "Hello, world!" end

Értékadás, üres utasítás

Az értékadás bal oldalán egy vagy több változó vagy mezőelérés található, amit egy ":=" jel követ, majd ezt követi egy tetszőleges kifejezés.
Amennyiben több változónak szeretnénk értéket adni, úgy a felsorolást N-esbe kell szervezni (azaz vesszővel elválasztani az értékeket, és bezárójelezni).
A ":=" operátor az egyszerű értékadás, melynel elösszor a jobb oldali kifejezés(ek) kiértékelése történik meg (több kifejezés esetén párhuzamosan) a bal oldali kifejezés-csoporttal egyidőben, majd maga az értékadás, páronként.
Az üres utasításra nincs kimondott nyelvi elem, esetleg üres blokkokat lehet definiálni.

Szekvencia

Kifejezések sorozatát egy do blokkba foglalhatjuk:

printThreeWords() = do print "print" print " three" print " words" end

Lehetőségünk van parallel kiértékelni kifejezéseket:
do factorial(10) also do factorial(5) also do factorial(2) end

Egyszerűbb formában is leírhatjuk ezt, egy N-es típusú kifejezés használatával:
(factorial(10), factorial(5), factorial(2))

A párhuzamos részek megfelelő interakcióinak tervezéséhez nyelvi szintű támogatás van elemi blokkok készítésére; az ilyen blokkok hatása kétféleképp érvényesül: a többi szál vagy úgy látja, hogy a blokk még nem futott le, vagy úgy látja, hogy a blokk lefutott, azaz egyetlen egy lépésben érvényesült a blokkban végrehajtott utasítássorozat.

atomic do x += 1 y += 1 end

Nézzünk meg egy komplexebb példát:
do x:ZZ32 := 0 y:ZZ32 := 0 z:ZZ32 := 0 atomic do x += 1 y += 1 also atomic do z := x + y end z end
A ZZ32 a 32 biten árbázolható, előjeles egész számok halmazát reprezentáló típus. A kifejezés típusa z típusa lesz, értéke pedig z értéke, ami vagy 0, vagy 2 lehet, ugyanis a sorrendiség nincs előírva a parallel futó részek számára, csak a tranzakcionáltság!

Elágazás

A nyelvben az if utasítást egy Boolean típusú kifejezés követi, majd egy "then" kulcsszó, majd egy kifejezés(blokk).
Amennyiben más feltételeket is ki szeretnénk értékelni, úgy használhatunk "elif" blokkokat (az "else if" helyett), melynek mindnek ugyanaz a szerkezete, mint a normál fornak. Ha feltétel nélküli ágat szeretnénk megadni, az "else" kulcsszó használható.
Az if kifejezés típusa annak a kifejezésblokknak a típusa lesz, amelyet végül kiértékel. Ha ilyen nem történik meg (pl nincs else ág), akkor a típusa () lesz.
Lezárható egy "end" kulcsszóval, akkor ezonban az else ág kötelező.

factorial(n) = if n = 0 then 1 else n factorial(n-1) end

A nyelv ismeri a case utasítást is, amelyet egy feltételes utasítás, egy opcionális operátor, és egy "of" követ, majd az esetek felsorolása, melyek mindegyike egy őrkifejezéssel kezdődik, amit egy "=>" követ, majd a kifejezés(blokk).
Tartalmazhat egy opcionális else ágat (ahol az őrkifejezés helyére kerül az else kulcsszó.)
A végét end jelzi.
A case kifejezés kiértékeli a feltételes utasítását, majd sorban kiértékeli az őrkifejezéseket, majd a megadott operátorral osszehasonlítja őket. Amennyiben nincs megadva operátor, úgy az egyenlő, vagy a tartalmazás operátorok kerülnek használatra.
Ha ez kiértékelve igaz, akkor a kifejezés(blokk) kiértékelésre kerül.
Az opcionális else ág összehasonlítás nélkül kerül lefutásra, ha a többi ág nem elégítette ki a feltételt.
Speciális esete a casenek a typecase kifejezés, ahol egy kifejezés értékét lehet vizsgálni, és az alapján elágaztatni (az x lokális változó itt deklarálódik, típusa a jobb oldali kifejezés típusa lesz). Amennyiben immutable az, amit vizsgálni szeretnénk, úgy a lokális változó bevezetése elhagyható.
typecase x = myLoser.myField of String => x "foo" Number => x + 3 Object => yogiBerraAutograph end

Ciklus

A nyelvben megtalálható a for és a while ciklus.
A while kulcsszó után egy feltételes kifejezés található, majd egy do blokk:
while x < 10 do println x x += 1 end

A for ciklusban a ciklusváltozót nem kell külön deklarálnunk, a típusa is kikövetkeztetésre kerül fordításkor. A ciklusváltozó lokális konstans.

for i <- 1:10 do print(i "") end
Egy nagyon fontos különbség a Fortress és más nyelvek között, hogy a for ciklus kiértékelése párhuzamosan történik alapesetben, azaz a fenti példakód tetszőleges sorrendben (és akár futásonként eltérően!) írhatja ki a számokat.

Egyéb vezérlő utasítások

A try-catch-finally blokkal, illetve az exit utasítással van lehetőségünk még megváltoztatni a vezérlési folyamot.