Az E programozási nyelv

A nyelv szintaxisa és szemantikája

Szekvencia (asszociativitása érdektelen)

A szekvencia, avagy utasítássorozat, egy kifejezés, melynek értéke az utolsó utasítás (amely szintén kifejezés) értéke. A szekvencia elemeit sorra végrehajtja a program. A szekvencia elemeit soronként újsor karakterrel választjuk el. A szekvencia elemeit írhatjuk egy sorba is, ilyenkor ’;’-vel választjuk el oket egymástól. A sorvégi ’;’ habár felesleges, nem hibás.

Beágyazott blokk

Szintaxis Jelentés Kifejtés
{
beágyazott scope kif.
}
A kezdo "{" után definiált minden definíció
elveszti a láthatóságát a "}" jel után
kernel

Feltételes elágazás

Szintaxis Kifejtés
if (cond-expr) {
then-expr
} else {
else-expr
}
kernel
if (cond-expr) {
then-expr
}
if (cond-expr) {
then-expr
} else {
null
}
if (cond-expr) {
then-expr
} else if ...
if (cond-expr) {
then-expr
} else {
if ...
}
switch (expr0) {
match patt1 {
expr1
}
...
}
{ def t := expr0
if (t =~ patt1) {
expr1
} else if ...
...
} else {
throw(***)
}
}

Az if-else kifejezés szemantikáját a Kernel-E definiálja a megszokott értelemben. Ha a feltételes kifejezést nem sikerül logikai értékké kiértékelni, kivétel lép fel. A feltételes kifejezésben definiált objektumok a then-expr kifejezésben láthatóak, az else-expr kifejezésben nem láthatóak.

Az összes többi feltételes elágazás konstrukció szerkezete, jelentése, láthatósága levezetheto az if-else kifejezés tulajdonságaiból.

Kivételkezelés

Szintaxis Jelentés Kifejtés
try {
expr0
} catch patt1 {
expr1
}
Ha expr0 patt1-hez illeszkedo
hibát dob hajtsd végre expr1-et
kernel
try {
expr0
} catch patt1 {
expr1
} catch patt2 {
expr2
} ...
Hajtsd végre az elso illeszkedo
blokkot
try {
expr0
} catch prob {
if (prob =~ patt1) {
expr1
} else if (prob =~ patt2) {
expr2
} else if ...
...
} else {
throw(prob)
}
}
try {
expr0
} finally {
expr1
}
Hajtsd végre expr1-et a kernel
elhagyása közben
kernel
try {
expr0
} catch patt1 {
expr1
} finally {
expr2
}
Amikor kombináljuk oket
catch-re is hatással van a
finally
try {
expr0
} catch patt1 {
expr1
} } finally {
expr2
}
try {
expr0
} catch patt1 {
expr1
} catch ...
...
} finally {
exprn
}
Természetesen a kombinált
esetben is használhatunk
több catch ágat
try {
expr0
} catch patt1 {
expr1
} catch ...
...
}
} finally {
exprn }

Az E támogatja a kivételkezelést. Egy catch blokk többféle kivételt is elkaphat – a kivételmintától függoen. A finally blokk minden esetben lefut a try blokk befejezodése elott (kivéve ha ott is kivétel lép fel). Kivételeket Throwable osztályok dobásával (throw) lehet explicit módon eloidézni.

A try utáni blokk tartalma nem látható a catch illetve a finally ágakban. A catch ágak illetve a finally ág külön blokknak minosülnek. Pl. a patt1-ben szereplo definiciók láthatóak az expr1-ben, de nem láthatóak semelyik másik catch ágban, se a finally ágban.

Az "escape" kifejezés

Szintaxis Jelentés Kifejtés
escape hatch {
expr
}
Ha hatch-et meghívják expr futása során,
akkor a kifejezés kiértékelése befejezodik,
a kifejezés értéke hatch argumentuma lesz.
Ha hatch() a hívás, akkor null lesz.
Ha hatch-t nem hívják meg, akkor a kifejezés
értéke expr értéke lesz.
kernel

Ezt a konstrukciót a ciklusok definiálásakor is felhasználjuk. A kifejezés a C++ és „leszármazottjai” exit, return, continue vezérlési utasításainak absztrakciója. A hatch-ban definiált kifejezések természetesen láthatóak a kifejezés törzsében is.

Ciklusok

Szintaxis Jelentés Kifejtés
while (cond-expr) {
expr
}
Amíg a feltétel igaz, értékeld ki expt-t.
Break-kel szakíthatjuk meg.
escape break {
loop(thunk {
escape continue {
if (cond) {
expr
} else {
break()
}
}
}
}
for vpatt in cexpr {
bexpr
}
Értékeld ki bexpr-t ismételten. for _ => vpatt in cexpr {
bexpr
}
for kpatt => vpatt in cexpr {
bexpr
}
Hajtsd végre bexpr-t amíg hatch-et
meg nem hívják
escape break {
def func(k,v) {
escape continue {
if (k =~ kpatt && \
v =~ vpatt) {
bexpr
} }
}
cexpr iterate(func)
}

A while ciklus a megszokott módon viselkedik. Amíg a feltétel (cond-expr) igaz, a ciklustörzs (expr) újra és újra lefut.

Ha a ciklus futása azért fejezodik be, mert a feltétel hamissá válik a ciklus értéke null lesz. A ciklusban meghívhatjuk a continue és break escape-kifejezéseket. A continue a törzs aktuális iterációjából „lép ki”, a break az egész ciklusból. Ha break escape kifejezéssel lépünk ki a ciklusból, akkor ennek az operandusa lesz a ciklus értéke.

A for ciklusok a kollekciók bejárására szolgálnak. A ciklus sorban bejárja a kollekció elemeit, minden lépésben megpróbálja az éppen aktuális elem értékét a megadott értékmintához (vpatt) illeszteni. Ha sikerrel jár, végrehajtja a törzs utasításait. Jellemzoen az értékminta egy változó neve, ilyenkor az illesztés mindig sikerül és a ciklusmag a kollekció minden elemére lefut. A for ciklus második változatában az értékekre és a kulcsokra egyaránt megadható egy értékminta illetve egy kulcsminta. A ciklusmag lefut a kollekció minden illeszkedo elemére. (Listák esetén a kulcs a lista adott elemére mutató index lesz.)

A for ciklus is használható a „hagyományos” módon, hiszen az „1..3” kifejezés egy intervallumot definiál, ami szintén kollekciónak számít.

Természetesen a ciklusok feltételében, illetve érték- és kulcsmintájában definiált objektumok láthatóak a ciklus törzsében is.