Az Alphard programozási nyelv

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

Program struktúra

A program egy fordítási egysége lehet blokk, vagy deklarációs lista. Ha ez egy blokk, akkor "program", a szó hagyományos értelmében. Ha ez egy deklarációs lista, akkor a hatásköre rendszerfüggõ.


<compilation unit> ::= begin <block> end | <exec decl list> <block> ::= {<exec decl list>;}#{<stmt>};+ {;}# <exec decl list> ::= {<exec decl>};* <exec decl> ::= <var decl> | <const dec> | <proc decl> | <form decl> | <label decl>

Egy blokk végrehajtása az alábbi sorrendben történik:

Kifejezések és utasítások:

A kifejezések és utasítások definiálják a végrehajtandó akciókat. Ezek kiértékelése eredményeként változik a program állapota. A kifejezések abban különböznek az utasításoktól, hogy van visszatérési értékük, míg az utasításoknak nincsen. Ezáltal minden kifejezés utasítás is egyben. Így ha ilyen környezetben használjuk, akkor a visszatérési érték érvénytelenítõdik.

<expression> ::= <invocation> | <conditional expression> | <value expression> | <with expression> | <first expression> <stmt> ::= <expression> | <loop stmt> | <exit stmt> | <null stmt> | <inner block> | <labelled stmt> | <assert stmt> <labelled stmt> ::= <identifier> : <stmt>
A címkézett utasítások utasításokból történõ kilépésre használatosak. A kilépés hatására a vezérlés azonnal átkerül a címkét követõ utasításra. A címkéket deklarálni kell, és hatáskörükön belül egyszer alkalmazhatók.

Eljáráshívások

<invocation> ::= <special literal> | <simple invocation>{<actuals>#|}(<invocation>) <actuals> ::= ({<actual>},*) <actual> ::= <expression> | <type description> <simple invocation> ::= {<identifier>$}*<identifier> | <special identifier>

Példák:
sin(x) integrate(F,a,b,eps) &:=(a,&+(b,c)) &:=(x,&subscript(V,i)) vector(int,1,unk)

Egy P paraméterek nélküli eljárás hívása:
P( ).

Feltételes kifejezések

<conditional expression> ::= <if expression> | <case expression> <if expression> ::= if <expression> then <block> {elif <expression> then <block>}* {else <block>}# fi <case expression> ::= case <expression> of <case> {elof <case>}* {else <block>}# esac <case> ::= {<expression>},+ :: <block>

Példák:
if a[i]>max then maxp:=i; max:=a[i]; fi y := if x>z then z else z fi if a<b then t:=1 elif a<c then t:=1 else t:=3 fi case IC of ADD::MB:=C[EA}; R:=R+MB elof SUB::MB:=C[EA}; R:=R-MB elof MUL::MB:=C[EA}; R:=R*MB else ERROR esac T:=case n of 1::MALE elof 2::FEMALE else NEUTER esac case i of 0,2,4::R:=0 elof 1,3::R:=1 elof esac
A feltételes kifejezések kifejezésként és utasításként is viselkedhetnek. Egy ilyen kifejezésnek akkor van értéke, ha: Az alábbi két kifejezés ekvivalens: 1.
if B1 then S1 elif B2 then S2 ... elif Bn then Sn else S0 fi

2. if B1 then S1 else if B2 then S2 else ... if Bn then Sn else S0 fi ... fi fi

A value kifejezés

<value expression> ::= value <identifier>{:<obk type>}# of <block> fo

Példák:
S:=value y:int of y:=0; for x:invec(A) do y:=y+1 od fo value A of Munge(A,43) fo

Egy value kifejezés utasítások szekvenciáját, illetve blokkokat konvertál át egy értékátadás kifejezéssé. A
    
value x:T of S fo

kifejezésben az x változó (aminek hatásköre S) definiálódik, és S végrehajtódik. Ha a hiányzik, mint a
   
value x of S fo

kifejezésben, akkor a meglévõ x változót használjuk. A value kifejezés értéke mindkét esetben Obj(x).

A with kifejezés

<with expression> ::= with <with list> in <block> ni <with list> ::= {<identifer>:<invocation>}+

Példák:
with Z:A[i].son[k] in Z.age:=0; Z.number:=k ni with R:x.y.z, Q:x.y.w in var s:T; s:=Q; Q:=R;R:=s ni

A with kifejezés bonyolultabb hívások egyszerûsítésére szolgál. A
    
with x:R in S ni
kifejezésben, ami R számítására szolgál, létrejön egy kötés x és R között, majd S ezzel a kötéssel értékelõdik ki. Ha a <block> egy egyszerû kifejezés, akkor a with kifejezésnek van értéke (a <block> értéke).

A first kifejezés

<first expression> ::= first <template> suchthat <expression> {then <block>}# {else <block>}# fi <template> ::= <identifier> from <invocation> | <identifier> from {<identifier>:}#<type description>

Példák:
first i from upto(1,n) suchthat A[i]>max then max:=A[i]; jmax:=i; fi y:=first x from invec(A) suchthat x>max then x else 0 fi

A first kifejezés a template-ben generált generátort (lásd késõbb) használja érték sorozatának létrehozására. Ezeket az értékeket a suchthat kulcsszó utáni logikai kifejezés ellenõrzi. Ha a
first x from g:Q suchthat B then S1 else S2 fi
first kifejezés értékére nincs szükség, akkor az alábbiakkal ekvivalens:
L1: begin L2: begin var g:Q; &start(g); do if &done(g) then &finish(g); leave L2 fi with x:&value(g) in if B then S1; &finish(g); leave L1 fi ni &next(g) od end L2 S2 end L1

ahol &start, &done, stb ... a Q form (vagy generator) által nyújtott szolgáltatások. Ha mind a then mind az else ág hiányzik, akkor az alapértelmezett skip helyettesítõdik be. Ha g: hiányzik, akkor egy sehol máshol nem használt azonosító helyettesítõdik be.
Vegyük észre, hogy S2 kiesik x és g hatáskörébõl. (Ezért ezeket itt nem használhatjuk.)
Ha a first kifejezésnek eredményt kell visszaadnia, akkor S1 és S2 egyszerû kifejezések kell legyenek, azonos visszatérési értékkel (legyen ez T):
   
value t:T of first x from g:Q suchthat B then t:=S1 else t:=S2 fi fo

Ciklusok

4 lehetõség van ciklus létrehozására:

<loop stmt> ::= <simple loop> | <while stmt> | <for stmt> <simple loop> ::= do <block> od <while stmt> ::= while <expression> <simple loop> <for stmt> ::= for <template> <single loop>

Példák:
do if x=y then exitloop fi if x>y then x:=x-y else y:=y-x fi od while x<>nil do P(car(x)); x:=cdr(x); od for x from invec(a) do x::=0 od

A
"do S od"

egyszerû ciklus S-et ismételi folyamatosan. Akkor terminál, ha egy kilépés utasítás (lásd késõbb) hívódik meg. A
"while B do S od"

ciklus szemantikailag ekvivalens az alábbi ciklussal:
do if not(B) then exitloop fi; S od

A
"for x from g:Q do S od"

ciklus szemantikailag ekvivalens az alábbi utasítással:
begin var g:Q; &start(g) do if &done(g) then exitloop fi with x: &value(g) in S ni &next(g) od &finish(g) end

A kilépés utasítás

<exit stmt> ::= exitloop | leave <identifier>

Például:
leave L exitloop

A leave L utasítás egy L -el címkézett utasításon belül érvényes, terminálja az utasítást. Az exitloop ciklusok belsejében érvényes, terminálja a ciklust.

Az üres utasítás

<null stmt> ::= skip

Az üres utasítást ki kell írni.

Belsõ blokk

<inner block> ::= begin <block> end | begin <block> endof {<identifier>#}

Ha az opcionális azonosítót kiírjuk, akkor a blokkot ezzel az azonosítóval kell címkézni, vagy a blokk egy ilyen nevû eljárás törzse kell legyen.

Az assert utasítás

<assert stmt> ::= assert <assertion>

Például:
do assert {GCD(x,y)=GCD(s0,y0)}; if x=y then exitloop fi if x>y then x-:=y else y-:=x fi od

Az assert utasítás egy feltételt ad meg, ami akkor értékelõdik ki, amikor a vezérlés az utasításra kerül. Helyességbizonyítási eszköz. Az <assertion>-t nem definiálja pontosan a nyelv.

Operátorok

Az Alphardban nem a hagyományos módon tekintjük az operátorokat, hanem úgy tekintjük az alkalmazásukat, mint függvényhívásokat. Így a programozó felüldefiniálhatja ezeket. Két fontos tulajdonság azonban így is igaz kell maradjon:

1. Asszociativitás: a legmagasabb és legalacsonyabb precedenciájú operátorok jobb, a többiek bal asszociatívak.

2. Precedencia: ^ (legmagasabb precedencia) * / div rem + - <= < = <> > >= not and cand or cor imp := +:= -:= *:= stb... (legalacsonyabb precedencia) A nyelvben az alábbi leképezések megengedettek (ha A egy unáris, B pedig bináris operátor): A <term> --> &A(<term>) <term1> B <term2> --> &B(<term1>,<term2>) <term1> B:= <term2> --> &:=(<term1>,&B(<term1>,<term2>)) Az alábbi operátorok automatikusan felülíródnak felüldefiniálás esetén, mint negációk: &<>(t1,t2) --> &not(&=(t1,t2)) &<=(t1,t2) --> &not(&>(t1,t2)) &>=(t1,t2) --> &not(&<(t1,t2)) Az alábbi operátorok automatikusan felülíródnak felüldefiniálás esetén, mint logikai operátorok:

t1 cand t2 --> if t1 then t2 else false fi t1 cor t2 --> if t1 then true else t2 fi

Operátorok felüldefiniálása csak új típusok definiálása esetén megengedett, meglévõ típusok operátorainak felüldefiniálására nincs lehetõség.