Sunteți pe pagina 1din 16

CAPITOLUL 3 LIMBAJE DE PROGRAMARE

1. CONCEPTELE PROGRAMARII CLASICE n acest capitol vom prezenta cteva dintre conceptele ntlnite n limbajele de programare imperative si orientate spre obiecte. Att aici, ct si n subcapitolele urmatoare ne vom alege exemplele din limbajele Ada, C++, FORTRAN, Java si Pascal. Dintre acestea, FORTRAN, Pascal si C sunt limbaje imperative din generatia a treia, C++ este un limbaj orientat spre obiecte derivat din C si C++. Ada a fost proiectat initial ca limbaj imperativ din generatia a treia cu multe caracteristici orientate spre obiecte, iar ultime versiune se apropie mai mult de paradigma orientata obiect. n anexa E veti gasi cte o scurta introducere n fiecare din aceste limbaje, precum si exemple de implementare n fiecare limbaj n parte a algoritmului de sortare prin inserare. De fapt, nu ne propunem sa prezentam n detaliu aceste limbaje, ci sa aratam sub ce forma apar n limbaje reale conceptele discutate. n principiu, instructiunile dintr-un limbaj de programare se mpart n trei categorii: instructiuni declarative, instructiuni imperative si comentarii. Instructiunile declarative au rolul de a defini terminologia specifica utilizata ulterior n program, cum ar fi numele folosite pentru referirea la diferite date; instructiunile imperative sunt cele care descriu pasii algoritmului implementat, iar comentariile mbunatatesc lizibilitatea programului, traducnd trasaturile sale ezoterice ntr-o forma mai usor de nteles. Fiecare modul de program ncepe n general cu o parte declarativa, n care terminologia este descrisa prin intermediul instructiunilor declarative, urmata de o parte procedurala, n care actiunile care trebuie executate sunt indicate prin intermediul instructiunilor imperative (ca n figura 3.1.). comentariile sunt presarate prin ntregul program, acolo unde se considera necesar.

Parte declarativa Modul de program Parte procedurala

Figura 3.1. Structura unui modul de program clasic Discutia noastra va avea aceeasi structura vom ncepe cu conceptele legate de instructiunile declarative, vom continua cu instructiunile imperative si vom ncheia cu problema documentatiei. Variabile, constante si literali Am aratat ca este mai avantajos sa identificam locatiile de memorie prin intermediul unor nume descriptive, dect prin adrese numerice. Ac esti identificatori sunt cunoscuti sub numele de variabile, ca o referire la faptul ca prin modificarea valorii stocate n locatia respectiva n timpul executiei programului, se schimba valoarea asociata identificatorului. Uneori nsa programul foloseste v alori predefinite, care nu se mai modifica. De exemplu, un program de control al traficului aerian n vecinatatea unui anumit aeroport face frecvente referiri la altitudinea la care este situat aeroportul fata de nivelul marii. Cel care scrie un astfel de program poate include literal aceasta valoare, sa zicem 645 de metri, ori de cte ori este necesar. O astfel de aparitie explicita a unei valori ntr-un program poarta numele de literal. Utiliznd astfel de valori vom obtine instructiuni de genul
assign EffectiveAlt the value (Altimeter 645)

unde EffectiveAlt si Altimeter sunt variabile, iar 645 este o valoare literala. n majoritatea cazurilor, utilizarea valorilor literale nu este o practica prea buna de programare, deoarece ele mascheaza ntructva semnificatia instructiunilor n care apar. De exemplu, de unde poate sa stie cel care citeste instructiunea din exemplul anterior ce reprezinta 645? n plus, folosirea valorilor literale complica inutil modificarea programului, atunci cnd aceasta devine necesara. Daca ducem
37

programul de control al traficului aerian la alt aeroport, toate referirile la altitudinea aeroportului vor trebui schimbate. Daca am folosit pentru aceasta altitudine valoarea literala 645, va trebui sa cautam si sa modificam toate aparit iile acesteia n program. Problema se complica si mai mult daca aceeasi valoare 645 apare n program si cu o alta semnificatie; n acest caz, de unde stim care dintre ocurentele valorii 645 trebuie schimbate si care nu? Ca solutie la astfel de probleme, limbajele de programare permit atribuirea de nume descriptive si unor valori particulare, care nu pot fi modificate. Aceste numere se numesc constante . De exemplu, n limbajul Pascal instructiunea declarativa 1
const AirportAlt = 645;

Asociaza constanta AirportAlt cu valoarea 645; n continuare, numele descriptiv AirportAlt va putea fi folosit oriunde n program n locul valorii 645. n exemplul nostru scris n pseudocod, instructiunea
assign EffectiveAlt the value (Altimeter 645)

va putea fi rescrisa astfel:


assign EffectiveAlt the value (Altimeter AirportAlt)

semnificatia instructiunii devenind astfel mult mai clara. n plus, daca n loc de valori literale se folosesc constante si programul este utilizat la alt aeroport, a carui altitudine este de exemplu de 267 metri, atunci nu trebuie schimbata dect instructiunea declarativa, care devine
const AirportAlt = 267

si toate referirile la altitudinea aeroportului vor lua n consideratie aceasta valoare. Tipuri de date Adesea, instructiunile declarative care atribuie datelor nume descriptive identifica n acelasi timp si tipul datelor. Tipul de date determina att modul n care este interpretat sirul respectiv de biti, ct si operatiile care pot fi efectuate cu data respectiva. Cele mai folosite tipuri sunt integer (ntreg), real, character (caracter) si boolean. Tipul integer se refera la date numerice ntregi, reprezentate cel mai adesea n complement fata de doi. Operatiile care pot fi efectuate cu ntregi sunt operatiile aritmetice clasice si comparatiile. Tipul real se refera la numere reale, stocate n general n virgula mobila. Operatiile care pot fi efectuate sunt aceleasi ca si pentru numere ntregi; observati nsa ca activitatile care trebuie executate pentru adunarea a doua numere reale sunt diferite de cele pentru adunarea a doi ntregi. Tipul character se refera la date care constau din simboluri, codificate de obicei n ASCII. Operatiile care pot fi efectuate asupra acestui tip de date sunt: comparatii care verifica daca un simbol apare sau nu naintea altuia n rodine alfabetica, testarea aparitiei unui sir de simboluri n cadrul altui sir si concatenarea unui sir de simboluri la sfrsitul altuia pentru a forma un sir mai lung. Tipul boolean se refera la acele date cu valori doar de adevarat sau fals, care apar ca urmare a efectuarii unor comparatii. Operatiile care pot fi compatibile cu acest tip sunt verificarile daca valoarea curenta este adevarat sau fals. n majoritatea limbajelor de programare este obligatoriu ca instructiunea declarativa care introduce o variabila sa specifice si tipul datelor la care se va referi variabila respectiva. n figura 3.2 sunt prezentate exemple de astfel de instructiuni declarative n Pascal, C, C++, Java si FORTRAN. n acest exemple variabilele Lenght si Width sunt declarate de tip real, iar Price, Tax si Total de tip ntreg. Observati ca n C, C++ si Java se foloseste pentru tipul real termenul float (deoarece aceste date sunt reprezentate n virgula mobila floating point). Vom vedea apoi n ce mod foloseste translatorul informatiile cu privire la tipurile de date pentru a traduce un program ntr-un limbaj de nivel nalt n limbaj masina. Deocamdata vom spune doar ca aceste informatii pot fi utilizate si pentru detectarea erorilor; de exemplu, operatii cum ar fi a dunarea a doua valori de tip caracter sau combinarea a doua date de tipuri diferite ar trebui sa ridice unele suspiciuni.
Declaratii de variabile n Pascal var Lenght, Widht; real; Price, Tax, Total: Declaratii de variabile n C, C++ si Java float Lenght, Width;
1

Ca si n cazul limbajelor naturale, limbajele de programare au adesea o cultura proprie. De exemplu, n Pascal si n Ada se obisnuieste sa se reprezinte cuvintele cheie cu aldine, asa cum am procedat si noi pentru pseudocod; aceasta practica nu este nsa raspndita printre utilizatorii limbajelor FORTRAN, C, C++ si Java. n exemplele noastre vom respecta pe ct posibil aceste obiceiuri culturale. 38

int Price, Tax, Total; Declaratii de variabile n FORTRAN REAL Lenght, Width; INTEGER Price, Tax, Total;

Figura 3.2 Declaratii de variabile n Pascal, C, C++, Java si FORTRAN Structuri de date Un alt concept asociat instructiunilor declarative este acela de structura de date, care se refera la forma conceptuala a datelor. Atunci cnd folosim siruri de caractere pentru a reprezenta numele unui angajat sau codul de identificare al unui produs nu este suficient sa declaram ca datele respective sunt de tip caracter; mai trebuie precizat si numarul de simboluri din care se compun. (De exemplu, pentru ca translatorul sa prelucreze o instructiune de mutare a numelui unui angajat dintr-o locatie n alta, el trebuie sa stie cte celule de memorie trebuie copiate). Prin urmare, pe lnga tip aceste date au si o lungime (marime). Din acest punct de vedere, un sir de caractere este un caz particular al unei structuri generice de date care poarta numele de vector omogen (homogeneous array). Vectorul omogen este un bloc de valori de acelasi tip, cum ar fi o lista unidimensionala, un tabel bidimensional cu linii si coloane, sau chiar tabele cu mai multe dimensiuni. Pentru a declara un astfel de vector, majoritatea limbajelor de programare utilizeaza o instructiune declarativa n care este precizata marimea pentru fiecare dimensiune a vectorului. De exemplu, n figura 3.3 puteti vedea instructiuni declarative n C si Pascal care declara Name ca vector unidimensional de tip caracter si lungime opt, iar Scores ca vector bidimensional de tip ntreg, cu doua linii si noua coloane. Spre deosebire de vectorii omogeni, n care toate datele sunt de acelasi tip, un vector heterogen (heterogenous array) este un bloc de date ale carui elemente pot fi de tipuri diferite. De exemplu, un bloc de date referitoare la un angajat poate contine o rubrica Name de tip caracter, o rubrica Age de tip ntreg si o rubrica SkillRating de tip real. n figura 3.3 puteti vedea cum este declarat un astfel de vector n limbajele C si Pascal. Dupa declararea vectorului se poate face referire la el n ntregime, prin nume, iar la fiecare componenta prin pozitie. n cazul vectorilor omogeni, componentele sunt identificate prin indici care specifica linia, coloana, etc. De exemplu, ntr-un program Pascal elementul situat pe a doua linie si a patra coloana ale vectorului Scores poate fi desemnata ca Scores [2, 4]; n C acelasi element va fi indicat ca Scores [1] [3]. (n C, numerotarea liniilor si coloanelor ncepe de la zero; de exemplu, elementul din prima linie si prima coloana este desemnat ca Scores [0] [0].)
Vectori declarati n Pascal var Name: packet array [1..8] of char; Scores: array [1..2, 1..9] of integer; Vectori declarati n C char Name [8] int Scores [2] [9]; Structura conceptuala a vectorilor Name:

Scores:

Figura 3.3 Declararea unor vectori omogeni n Pascal si C La elementele vector heterogen se face de regula referire prin identificatorul vectorului si numele componentei respective, separate prin punct. De exemplu, componenta Age a vectorului Employee din figura 3.4 va fi desemnat att n C ct si n Pascal prin EmployeeAge. Forma asociata a structurii de date exista de fapt doar n mintea programatorului, n realitatea fizica datele componente ale unui vector putnd fi mprastiate ntr-o zona larga a memoriei principale sau a memoriei permanente. Acesta este motivul pentru care spunem ca structura de date este forma conceptuala a datelor.
39

Instructiuni de atribuire Probabil ca cel mai bun exemplu de instructiune imperativa este instructiunea de atribuire, care cere ca unei variabile sa i se atribuie o valoare. n general, o astfel de instructiune are urmatoarea sintaxa: variabila, urmata de un simbol care reprezinta operatia de atribuire si de o expresie care indica valoarea care se atribuie. Semantica este urmatoarea: expresia este evaluata, iar rezultatul este atribuit variabilei, ca valoare. De exemplu, n C si C++ instructiunea
Total = Price + Tax;

cere ca variabilei Total sa i fie atribuita valoarea sumei dintre Price si Tax. n Ada si Pascal instructiunea echivalenta ar fi
Total := Price + Tax; Vector declarat n Pascal var Employee: record Name: packet array [1..8] of char; Age: integer; SkillRating: real Vector declarat n C struct { char Name [8]; int Age; float SkillRating; } Employ ee; Organizarea conceptuala a vectorului Employee

Name

Age

SkillRating

Figura 3.4 Declararea unor vectori heterogeni n Pascal si C Observati ca aceste instructiuni difera numai prin sintaxa operatorului de atribuire, care n C si C++ este reprezentat doar prin semnul egal, n tip ce n Ada si Pascal se compune din simbolul doua puncte urmat de semnul egal. n paradigmele imperativa si orientata spre obiecte, instructiunea de atribuire este foarte mult folosita, deoarece datele sunt manipulate n principal prin intermediul sau. ntr-un fel, scopul instructiunilor declarative este de a stabili o terminologie care sa poata fi folosita n instructiunile de atribuire, iar rolul instructiunilor de control, pe care le vom studia imediat, este de a stabili ordinea n care vor fi executate aceleasi instructiuni de atribuire. Mare parte din puterea instructiunilor de atribuire provine din faptul ca expresiile din dreapta pot fi de cele mai diverse feluri; n general, aici pot fi folosite expresii algebrice de orice tip, continnd operatiile aritmetice de adunare, scadere, nmultire si mpartire (reprezentate de regula prin simbolurile obisnuite, +, -, * si /). Dar modul n care sunt interpretate aceste expresii poate sa difere de la un limbaj la altul. De exemplu, expresia 2 * 4 +6 / 2 poate duce la rezultatul 14 daca este evaluata de la dreapta la stnga, sau 7 daca este evaluata de la stnga la dreapta. n mod normal, ambiguitatile sunt rezolvate prin stabilirea unor reguli de precedenta a operatorilor, ceea ce nseamna ca unele operatii au prioritate fata de altele. Regulile clasice ale algebrei stabilesc ca nmultirea si mpartirea au prioritate fata de adunare si scadere, ceea ce face ca mai nti sa se execute nmultirile si mpartirile si abia dupa aceea adunarile si scaderile. Potrivit acestei conventii, expresia anterioara va da rezultatul 11. n cel mai multe limbaje, pentru a forta efectuarea operatiilor n alta ordine dect cea stabilita de regulile de precedenta se folosesc paranteze; astfel, expresia 2 * (4 + 6) / 2 va da rezultatul 10. Expresiile care apar n instructiunile de atribuire pot sa implice si alte operatii dect cele algebrice. De exemplu, daca First si Last sunt variabile asociate cu siruri de caractere, instructiunea FORTRAN
Both = First / / Last

40

face ca variabilei Both sa i fie atribuit sirul de caractere obtinut prin concatenarea valorilor variabilelor First si Last. Astfel, daca First si Last au asociate sirurile abra, respectiv cadabra, atunci lui Both i se va atribui sirul abracadabra. n multe limbaje de programare exista simboluri care pot sa reprezinte mai multe tipuri de operatii, semnificatia simbolului respectiv ntr-un anumit context fiind determinata de tipul operanzilor. De exemplu, simbolul + indica n mod normal adunarea, atunci cnd operanzii sunt numerici; dar n unele limbaje, cum ar fi Java, acelasi simbol indica n cazul operanzilor de tip sir de caractere operatia de concatenare. Utilizarea n acest mod a unui singur simbol pentru a reprezenta mai multe operatii se numeste suprancarcare (overloading). Instructiuni de control Instructiunile de control sunt instructiuni imperative care modifica ordinea de executie a programului. Dintre toate instructiunile, acestea sunt cele care au atras n mod deosebit atentia, strnind cele mai multe controverse. Principalul vinovat este cea mai simpla dintre instructiunile de control, instructiunea goto, care furnizeaza o metoda de a continua executia programului din alt punct, care a fost etichetat n acest scop cu un nume sau cu un numar. Dupa cum puteti vedea, este vorba de aplicarea directa a instructiunii de salt din limbajul masina. Problema este ca includerea unei astfel de instructiuni ntr-un limbaj de nivel nalt permite scrierea unor secvente foarte nclcite, de genul
goto 40 20 Total = Price + 10 goto 70 40 if Price < 50 goto 60 goto 20 60 Total = Price + 5 70 stop

cnd de fapt acelasi lucru se poate face cu numai doua instructiuni:


if Price < 50 then Total = Price + 5 else Total = Price + 10 stop

Pentru a evita astfel de secvente complexe, limbajele moderne dispun de instructiuni de control mai elaborate, cum este instructiunea if-then-else, care permite ramificarea programului prin intermediul unei singure structuri sintactice. Alegerea structurilor de control care sunt ncorporate ntr-un limbaj constituie una dintre cele mai importante decizii de proiectare. Scopul este ca limbajul nu numai sa permita ca algoritmii sa fi exprimati ntr-o forma ct mai lizibila, dar si sa ajute pe programator sa obtina aceasta lizibilitate, ceea ce se realizeaza prin restrictionarea utilizarii structurilor care s-au dovedit a duce la programe greoaie si ncurajarea folosirii unor structuri mai bine proiectate. Rezultatul este acea practica nu ntotdeauna bine nteleasa, numita programare structurata, care presupune att o metodologie de proiectare organizata, ct si utilizarea adecvata a instructiunilor de control oferite de limbaj. Ideea este sa se obtina un program usor de nteles, care sa respecte specificatiile. Figura 3.5 prezinta cteva dintre cele mai utilizate structuri de ramificare si instructiunile de control furnizate de diverse limbaje de programare pentru reprezentarea acestora. Observati ca primele doua structuri sunt cele pe care le-am ntlnit deja n capitolul anterior, redate n pseudocod prin instructiunile if-then-else, respectiv while. Cea de a treia structura, cunoscuta sub numele de structura case, poate fi vazuta ca o extindere a structurii if-then-else; n timp ce struc tura ifthen-else permite alegerea ntre doua optiuni, structura case permite selectarea unei optiuni dintr-o gama mai larga.

41

Figura 3.5 Structuri de control si reprezentarea lor n Pascal, C, c++, Java si Ada O alta structura larg folosita, numita adesea structura for, ca si reprezentarile ei n diferite limbaje, sunt prezentate n figura 3.6. Aceasta structura ciclica este similara instructiunii while pe care am folosit-o n pseudocod, cu diferenta ca initializarea, modificarea si ncheierea ciclului sunt ncorporate ntr-o singura instructiune. O astfel de instructiune este foarte convenabila atunci cnd corpul buclei se executa cte o data pentru fiecare valoare dintr-un anumit domeniu ordonat. De exemplu, instructiunile din figura 3.6 duc la executia corpului buclei o data cu valoarea lui Count fiind 1, din nou cu valoarea lui Count fiind 2 si nca o data cu valoarea 3. Scopul acestor exemple este sa demonstreze ca structurile generice de ramificare apar, cu mici variatii, n toate limbajele imperative si orientate spre obiecte. Un rezultat ntructva surprinzator al informaticii tactice este acela ca abilitatea de a exprima doar cteva dintre aceste structuri asigura oricarui limbaj de programare capacitatea de a exprima orice problema care are o solutie algoritmica. nvatarea unui limbaj de programare nu nseamna nvatarea unui sir fara numar de instructiuni de control; de fapt, principalele instructiuni de control ale oricarui limbaj de programare pot fi numarate pe degetele de la o singura mna.

42

Figura 3.6 Structura for si reprezentarea ei n Pascal, C, C++ si Java Comentarii Experienta arata ca orict de bine ar fi proiectat un limbaj de programare si orict de bine ar fi el folosit, informatiile suplimentare sunt ntotdeauna binevenite, daca nu cumva strict necesare pentru orice om care ncearca sa nteleaga un program de o oarecare complexitate. Din acest motiv, limbajele de programare furnizeaza o sintaxa pentru inserarea n program a unor instructiuni explicative, numite comentarii. Documentatia constituita din aceste comentarii se numeste documentatie interna, deoarece ea nu apare ntr-un document separat, ci chiar n cadrul programului. Documentatia interna este ignorata de catre translator, de aceea prezenta sau absenta ei nu are nici o importanta pentru calculator. Cu sau fara comentarii, versiunea n limbaj masina a programului va fi aceeasi, dar informatiile furnizate de aceste instructiuni constituie, din punctul de vedere uman, o parte importanta a programului. n lipsa unei astfel de d ocumentatii, programele foarte complexe pot usor sa depaseasca puterea de ntelegere totusi limitata a programatorului uman. Pentru a permite inserarea comentariilor n program, limbajele de programare furnizeaza doua metode de delimitare a acestora de restul programului. O metoda este aceea de a se include ntregul comentariu ntre niste marcaje speciale, cea de a doua este sa se marcheze doar nceputul comentariului, acesta urmnd sa ocupe tot restul rndului. n acest ultim caz, comentariul este ncheiat de la nceputul liniei urmatoare. Limbajele Pascal si C folosesc prima dintre metode; n Pascal, nceputul comentariului este marcat cu simbolul {, iar sfrsitul cu }, n timp ce n C nceputul este indicat prin /* iar sfrsitul prin /. Limbajele Ada si FORTRAN utilizeaza cea de a doua tehnica; n Ada, nceputul comentariul se marcheaza cu doua liniute de unire (--), iar n FORTRAN cu semnul exclamarii. n ambele cazuri, comentariul se extinde pe tot restul liniei; daca se doreste ca el sa continue si pe rndul urmator, nceputul rndului trebuie sa fie marcat n acelasi mod. Limbajele C++ si Java utilizeaza ambele metode. Fiind derivate din c, ele accepta comentariile incluse ntre ele / si */, dar permit n plus si alte comentarii care ncep cu // si se extind pe tot restul rndului. Astfel, n C++ si Java att
/* Acesta este un comentariu. */

ct si
// Acesta este un comentariu.

sunt instructiuni de comentariu valide. Acum cteva cuvinte despre ce nseamna un comentariu cu adevarat util. Programatorii ncepatori, atunci cnd li se cere sa-si documenteze programul au tendinta sa scrie dupa o instructiune de genul
Total := Price + Tax;

un comentariu cum ar fi alculeaza Total ca suma dintre Price si Tax. Evident ca astfel de C comentarii redundante nu clar ifica programul, ci doar l lungesc nejustificat. Nu uitati ca scopul documentatiei interne este sa explice programul, nu sa-l repete. n exemplul nostru, un comentariu mai util ar putea sa explice de ce se calculeaza totalul (binenteles, daca acest lucru nu este evident). De exemplu, un comentariu de genul Total este utilizat ulterior pentru a se calcula GrandTotal, dupa care nu mai este folosit ar fi mult mai util dect precedentul.
43

n plus, un program care este presarat din loc n loc cu comentarii po ate fi uneori chiar mai greu de citit dect unul complet nedocumentat. De aceea, este recomandabil ca toate comentariile care se refera la un anumit modul de program sa fie grupate ntr-un singur loc, de exemplu la nceputul modulului. n acest fel cititorul va sti unde trebuie sa caute explicatiile de care are nevoie; tot aici pot fi descrise scopul si caracteristicile principale ale modului respectiv. Daca se adopta acest format pentru toate modulele programului, acesta va capata un anumit grad de uniformitate, fiecare modul constnd dintr-un bloc de instructiuni explicative, urmat de prezentarea sa formala. Aceasta practica va creste considerabil lizibilitatea programului. 2. MODULE DE PROGRAM Divizarea programelor de mari dimensiuni n modul este mai u de controlat prezinta o serie de sor avantaje, iar limbajele de programare dispun de multe metode de punere n practica a acestei descompuneri. Limbajele bazate pe paradigma functionala mpart n mod natural programele n functii, iar limbajele bazate pe paradigma orientata spre obiecte au ca rezultat module de program care reprezinta obiectele. n acest subcapitol ne vom concentra asupra tehnicilor prin care se poate obtine o reprezentare modulara a unui algoritm. Metoda este aceea de grupare a pasilor care compun algoritmul, constituinduse astfel mici portiuni de algoritm care sunt folosite ca instrumente abstracte pentru exprimarea produsului final. Va rezulta o structura de subprogram ca cea pe care am folosit-o n pseudocod sub numele de procedura. Proceduri n sens generic, procedura este un modul de program scris independent de programul principal, dar legat totusi de acesta printr-un proces de transfer/revenire (asa cum se vede n figura 3.7) atunci cnd este nevoie de serviciile procedurii. Controlul este transferat acesteia (prin intermediul unei instructiuni JUMP n limbaj masina), iar dupa ce executia procedurii respective s-a ncheiat controlul revine modulului principal. Procesul de transfer al controlului este numit adesea apelare sau invocare a procedurii respective, iar modulul care solicita executia procedurii se numeste modul apelant. n limbajele de programare pe care le-am oferit ca exemple, procedurile sunt definite ntr-un mod asemanator celui din pseudocodul utilizat n capitolul anter ior. n multe privinte, o procedura este un program n miniatura; ea consta din instructiuni declarative, care descriu variabilele si constantele utilizate n cadrul procedurii, si din instructiuni imperative, care arata pasii ce trebuie urmati la executia acesteia. Definitia ncepe printr-o instructiune numita antetul procedurii (procedure s header), care precizeaza printre altele numele procedurii. Dupa antet urmeaza instructiunile declarative si imperative care definesc procedura. Ca regula generala, var iabilele declarate n interiorul unei proceduri sunt variabile locale, ceea ce nseamna ca ele pot fi utilizate doar n interiorul procedurii respective. Aceasta regula elimina confuziile care ar putea sa apara n cazul n care doua proceduri scrise n mod independent ar folosi variabile cu acelasi nume. Sunt totusi cazuri n care unele date trebuie utilizate n comun de toate modulele unui program. O astfel de variabila se numeste variabila globala, si majoritatea limbajelor dispune de metode de declarare att pentru variabile locale, ct si pentru variabile globale.

Figura 3.7 Transferul controlului la apelarea unui subprogram


44

Sintaxa utilizata pentru a se solicita executia unei proceduri din alt modul al programului difera destul de putin de la un limbaj la altul: FORTRAN utilizeaza n acest scop cuvntul cheie CALL, n timp ce Ada, C, C++, Java si Pascal folosesc pur si simplu numele procedurii respective. Astfel, daca GetNames, SortNames si WriteNames sunt proceduri pentru introducerea, sortarea si tiparirea unei liste de nume (identificata printr-o variabila globala), le vom putea folosi ntr-un program pentru a citi, sorta si tipari lista scriind n FORTRAN secventa de instructiuni
CALL GetNames CALL SortNames CALL WriteNames

iar n Ada, C, C++, Java si Pascal instructiunile


GetNames; SortNames; WriteNames;

Observati ca n acest mod am obtinut un program de numai trei instructiuni, fiecare dintre ele solicitnd serviciile unui instrument abstract; detaliile referitoare la modul n care actioneaza fiecare dintre aceste instrumente sunt cuprinse si izolate n cadrul definitiei procedurii respective. Parametri Asa cum vom vedea ceva mai trziu, folosirea n comun a unor informatii prin utilizarea unor variabile globale nu este recomandabila, deoarece un asemenea mod de lucru tinde sa mascheze ntructva activitatile modulelor de program care partajeaza datele respective. O metoda mai buna este aceea de a identifica datele partajate de mai multe module de program ntr-un mod mai clar, ceea ce se poate face prin includerea explicita a listei acestora n instructiunea prin care se solicita executia procedurii. Prin urmare, si antetul procedurii va trebui sa contina o lista a variabilelor carora li se atribuie valori la apelarea procedurii. Elementele care compune aceste doua liste se numesc parametri. Atunci cnd este apelata procedura, lista de parametri din modulul apelant este asociata, element cu element, listei de parametri din antetul procedurii. n majoritatea cazurilor, valor ile parametrilor din modulul apelant sunt transferate efectiv parametrilor corespondenti din procedura. Dupa aceea, procedura este executata, iar valorile eventual, modificate. 3.
IMPLEMENTAREA LIMBAJELOR

n acest subcapitol vom analiza procesul de convertire a unui program scris ntr-un limbaj de nivel nalt ntr-o forma executabila de catre masina. Procesul de translatare Procesul de convertire a unui program dintr-un limbaj n altul se numeste translatare. Programul n forma initiala este programul sursa, iar versiunea translatata este programul obiect. Procesul de translatare consta din trei activitati - analiza lexicala, analiza sintactica (parsing) si generarea codului efectuate de trei module distincte ale translatorului, numite analizor lexical, analizor sintactic (parser) si generator de cod (figura 3.8). Analiza lexicala este procesul prin care se identifica sirurile de simboluri din programul sursa care reprezinta entitati distincte. De exemplu, cele trei simboluri din sirul 153 nu trebuie interpretate ca 1 urmat de 5 urmat de 3, ci recunoscute ca reprezentnd o valoare numerica. La fel, un cuvnt care apare n cadrul programului, desi compus din mai multe simboluri, trebuie interpretat ca o singura entitate. Oamenii efectueaza aceasta analiza lexicala fara efort constient: atunci cnd ni se cere sa citim cu voce tare pronuntam cuvinte, nu caractere individuale.

Figura 3.8 Procesul de translatare


45

Pe masura ce identifica grupuri de simboluri care constituie entitati distincte, analizorul lexical le clasifica n functie de ceea ce reprezinta o valoare numerica, un cuvnt, un operator aritmetic etc. si genereaza un model de biti cunoscut sub numele de simbol (token), care arata clasa entitatii respective. Aceste simboluri devin datele de intrare pentru analizor. Analiza sintactica este un proces de identificare a structurii gramaticale al programului si de recunoastere a rolului fiecarei componente. Modul ei de abordare este responsabilul pentru eventualele ezitari atunci la citirea unei fraze de genul
Confectionam manusi pentru doamne din piele.

Pentru a simplifica procesul de analiza sintactica, primele limbaje au insistat asupra cerintei ca fiecare instructiune sa fie plasata ntr-un anumit fel n cadrul programului. Aceste limbaje erau cunoscute sub numele de limbaje cu format fix. zilele noastre, majoritatea limbajelor de programare sunt n limbaje cu format liber, ceea ce nseamna ca locul instructiunilor n cadrul programului nu are importanta. Astfel, programatorul are posibilitatea de a-si organiza programul ntr-o forma care sa fie ct mai usor de citit de catre el, si nu de catre translator. n cazul lor se utilizeaza frecvent indentarea pentru a evidentia structura unei instructiuni. Astfel, n loc sa scrie o instructiune sub forma
if Cost < numerar disponibil then plateste n numerar else foloseste cartea de credit

un programator ar putea alege forma


if Cost < numerar disponibil then plateste n numerar else foloseste cartea de credit

Pentru ca un calculator sa poata analiza sintactic un program scris ntr-un limbaj cu format liber, sintaxa limbajului trebuie proiectata astfel nct structura programului sa poata fi identificata indiferent de spatiile utilizate n programul sursa. n acest scop, majoritatea limbajelor cu form at liber folosesc semnele de punctuatie, cum ar fi semnul punct si virgula, pentru a marca sfrsitul unei instructiuni, precum si cuvintele cheie, cum sunt if, then sau else, pentru a marca nceputul unor propozitii distincte. Aceste cuvinte cheie sunt n majoritatea cazurilor cuvinte rezervate, n sensul ca nu pot fi folosite de catre programator n alte scopuri n cadrul programului. Procesul de analiza sintactica se bazeaza, pe un set de reguli care definesc sintaxa limbajului de programare. O metoda de a exprima aceste reguli o reprezinta diagramele de sintaxa, care sunt reprezentari grafice ale structurii gramaticale a programului. Figura 3.9 prezinta diagrama de sintaxa a instructiunii if-then-else din pseudocodul utilizat n anterior. Aceasta diagrama arata ca structura if-then-else ncepe cu cuvntul if, urmat de o expresie booleana, urmata de cuvntul then, urmat de o instructiune. Combinatia poate sau nu sa fie urmata de cuvntul else si de o alta instructiune. Observati ca termenii care apar ca atare n instructiunea if-then-else sunt nscrisi n ovale, n timp ce termenii care necesita detalierea ulterioara, cum sunt expresie booleana si instructiune, sunt inclusi n dreptunghiuri. Acestia din urma (din dreptunghiuri) se numesc nonterminali, iar dinti, terminali, n descrierea completa a sintaxei limbajului, nonterminalii sunt descrisi prin alte diagrame. Ca un exemplu mai complet, figura 3.10 prezinta un set de diagrame care descriu sintaxa unei structuri denumite Expresie. Prima diagrama defineste o Expresie ca fiind constituita dintr-un Termen care poate sa fie urmat sau nu de un simbol + sau - si de o alta Expresie, iar a doua descrie un Termen ca fiind un simbol x, y, sau z sau un Termen urmat de un simbol * sau / si de o alta Expresie. Modul n care un anumit sir de caractere se conformeaza unui astfel de set de diagrame de sintaxa poate fi reprezentat n forma grafica printr-un arbore de analiza sintactica, asa cum este cel din figura 5.16, care corespunde sirului x + y * z si setul de diagrame din figura 3.11. Observati ca arborele pleaca de la o Expresie nonterminala si ca la fiecare nivel nonterminalii de la acel nivel sunt descompusi pna cnd sunt obtinute chiar simbolurile din sirul dat.

46

Figura 3.9 Diagrama de sintaxa a instructiunii if-then-else din pseudocod

Figura 3.10 Diagrame de sintaxa care descriu structura unei expresii algebrice simple

Figura 3.11 Arborele de analiza sintactica pentru sirul x + y + z, realizat pe baza diagramelor de sintaxa din figura 3.10 Proces ul de analiza sintactica consta n esenta din construirea arborelui de analiza sintactica a programului sursa. De aceea, regulile de sintaxa care descriu structura gramaticala a unui program nu trebuie sa permita obtinerea a doi arbori diferiti pentru acelasi sir analizat, deoarece aceasta ar crea ambiguitati n cadrul analizei. Aceste erori pot sa fie destul de subtile. De exemplu, regula din figura 3.9 contine o eroare care permite ca pentru instructiunea
if B1 then if B2 then S1 else S2

sa se obtina doi arbori diferiti, prezentati n figura 3.12. Observati ca cele doua interpretari difera semnificativ: prima implica executia instructiunii S2 n cazul n care B1 este fals, iar a doua face ca instructiunea S2 sa se execute numai daca B1 este adevarat, iar B2 fals. Definitiile de sintaxa ale limbajelor formale de programare sunt proiectate astfel nct sa evite asemenea ambiguitati. n cazul nostru, vom exclude ambiguitatile cu ajutorul parantezelor; astfel, pentru a distinge ntre cele doua interpretari posibile vom scrie:
47

if Bl then (if B2 then S1) else S2

si
if B1 then (if B2 then S1 else S2)

Figura 3.12 Doi arbori de analiza sintactica diferiti pentru instructiunea if B1 then if B2 then S1 else S2 Pe masura ce primeste simbolurile de la analizorul lexical, analizorul sintactic prelucreaza instructiunile declarative si imperative, ignornd comentariile. Informatiile extrase din instructiunile declarative sunt nregistrate ntr-o tabela numita tabela de simboluri, care contine date referitoare la variabilele care au fost declarate si la tipurile si structurile de date asociate lor. Atunci cnd analizeaza instructiunile imperative, cum ar fi
assign Total the value Price + Tax;

analizorul sintactic se serveste de informatiile din tabela de sim boluri. ntr-adevar pentru a sti care este semnificatia simbolului +, analizorul trebuie sa cunoasca tipul de date asociate variabilelor Price si Tax. Astfel, daca Price este de tip real iar Tax de tip caracter, atunci adunarea lor nu are sens si trebuie r portata ca eroare. Pe de alta parte daca Price si Tax sunt ambele de tip ntreg, atunci a analizorul sintactic va ce generatorului de cod sa construiasca o instructiune n limbaj masina utiliznd codul de operatie pentru adunarea ntregilor; iar daca cele doua variabile sunt de tip atunci analizorul va cere utilizarea codului pentru adunare n virgula mobila. Instructiunea precedenta are o semnificatie si daca tipurile de date sunt diferite. De exemplu, daca Price este ntreg iar Tax este real, adunarea se p oate face, analizorul va alege probabil sa-i spuna generatorului de cod sa converteasca mai nti o valoare la tipul celeilalte si de-abia pe urma sa efectueze adunarea. Aceste conversii implicite ntre tipuri poarta numele de coercitii. Coercitiile nu sunt n general agreate de autorii limbajelor de programare, care spun ca aparitia lor indica de obicei o scapare n proiectarea programului si nu ar trebui acceptata de analizorul sintactic. Prin urmare, majoritatea limbajelor moderne de programare sunt stricte n ceea ce priveste tipurile (strongly
48

typed), ceea nseamna ca toate activitatile solicitate de program trebuie sa implice date compatibile fara coercitii. Analizoarele sintactice ale acestor limbaje raporteaza ca erori toate conflictele de tip. Ultima activitate din cadrul translatarii unui program, generarea codului, este procesul de construire a instructiunilor din limbajul masina care simuleaza instructiunile recunoscute de analizorul sintactic. Procesul se preteaza la multe discutii; una dintre preocupari este de exemplu aceea de a produce cod eficient. De exemplu, sa studiem translatarea n cod masina a instructiunilor
assign x the value y + z; assign w the value x + z;

Aceste instructiuni ar putea fi desigur translatate n mod individual, dar codul astfel produs nu ar fi eficient. Generatorul de coduri ar trebui proiectat n asa fel nct sa-si dea seama ca dupa efectuarea primei instructiuni valorile lui x si z sunt deja n registrii de uz general al unitatii centrale si nu mai trebuie ncarcate din memoriei pentru a se calcula valoarea lui w. Este ceea ce se numeste optimizarea codului, una dintre sarcinile importante ale generatorului de cod. Trebuie spus ca analiza lexicala, analiza sintactica si generarea codului nu se realizeaza strict n aceasta ordine, ci se mpletesc: analizorul lexical ncepe prin identifica primul simbol si l trece analizorului sintactic, care ofera analizorului lexical un indiciu cu privire la structura care ar putea sa urmeze si i cere urmator simbol. n momentul n care recunoaste instructiuni sau propozitii complete, analizorul sintactic apeleaza generatorul de cod, care produce instructiunile masini necesare. Editarea de legaturi si ncarcarea Programul obiect care rezulta n urma procesului de translatare, desi exprimat n limbaj masina, este arareori ntr-o forma direct executabila. Unul dintre motive este acela ca majoritatea mediilor de programare permit dezvoltarea si translatarea individuala a modulelor de program, la momente diferite (ceea ce permite constructia modulara a produselor software). Astfel, programul obiect produs n urma unui proces de translatare este adesea numai una din piesele necesare unui program complet, iar fiecare piesa are nevoie de serviciile celorlalte, scopul final fiind ndeplinirea sarcinii ntregului sistem. Chiar daca programul este dezvoltat si translatat sub forma unui singur modul, n cele mai multe cazuri programul obiect tot nu este pregatit pentru executie, deoarece contine probabil cereri de servicii software care sunt oferite direct de sistemul de operare sau pot fi obtinute prin intermediul acestuia. Astfel, un program obiect este de fapt un program n limbaj masina caruia i lipsesc unele legaturi, legaturi care trebuie nnodate pentru a se obtine un program executabil. nnodarea acestor legaturi este efectuata de un program numit editor de legaturi (linker). Sarcina lui este de a lega ntre ele mai multe programe obiect (rezultate anterior prin translatari independente), rutine ale sistemului de operare si alte utilitare software ntr-un program executabil (numit si modul ncarcabil), ce va fi memorat ca fisier n sistemul de stocare de masa al calculatorului. n fine, pentru executia unui program astfel translatat, el trebuie plasat n memorie de catre un program numit program de ncarcare (loader) care este de obicei parte a secventiatorului. Importanta acestui pas este foarte mare n cazul sistemelor multitasking, n care zona exacta de memorie disponibila pentru program nu este cunoscuta dect n momentul rularii sale (deoarece programul trebuie sa mparta memoria cu celelalte procese care se executa n acelasi timp) si variaza de la o executie la alta. n acest context, sarcina programului de ncarcare este aceea de a plasa programul n zona de memorie identificata de s istemul de operare si de a face ajustarile de ultima clipa (ultima microsecunda) necesare n momentul n care este cunoscuta localizarea exacta a programului n memorie. (O instructiune de salt dintr-un program trebuie sa execute un salt la adresa corecta n cadrul programului respectiv.) n dorinta de a minimiza aceste ajustari de ultim moment, au fost ncurajate tehnicile prin care se evita referintele explicite la adrese de memorie, ceea ce duce la programe (numite si module relocatabile) care, fara nici o modificare, se executa corect indiferent de adresa la care sunt ncarcate n memorie.

Figura 3.13 Procesul complet de pregatire a programului Pe scurt, pregatirea unui program scris ntr-un limbaj de nivel nalt consta dintr-o secventa de trei pasi: translatare, editare de legaturi si ncarcare, asa cum puteti vedea n figura 3.13. Dupa realizarea primilor doi pasi - translatarea si editarea de legaturi - programul poate fi ncarcat si executat n mod
49

repetat, fara a se mai reveni la versiunea sursa. Daca sunt nsa necesare modificari n program, acestea se executa n programul sursa, dupa care sursa modificata este translatata si se face editarea de legaturi, obtinndu-se un nou modul ncarcabil, care sa reflecte modificarile efectuate. Pachete pen tru dezvoltarea produselor software Tendinta curenta este aceea de a grupa translatorul si celelalte elemente software utilizate n procesul de dezvoltare a unui produs software ntr-un pachet care functioneaza ca un sistem integrat. Conform schemei de clasificare un astfel de sistem va fi considerat un software de aplicatie. ntr-o astfel de aplicatie programatorul are acces la un editor n care sa-si scrie programele, la un translator pentru conversia acestora n limbaj masina si la o varietate de instrumente de depanare pentru a urmari executia unui program care nu functioneaza corect, n vederea depistarii locului n care o ia razna. Avantajele utilizarii unui astfel de sistem integrat sunt numeroase. Probabil ca cel mai evident dintre ele este ca programatorul poate trece cu usurinta de la editor la instrumentele de depanare, modificnd si testnd imediat programul. n plus, multe pachete integrate permit legarea modulelor de program dezvoltate separat ntr-o maniera care simplifica accesul la componentele nrudite. Unele sisteme nregistreaza informatii cum ar fi de pilda care dintre modulele implicate a fost modificat de ultima testare. Aceste facilitati sunt foarte utile mai ales pentru dezvoltarea sisteme software de mari dimensiuni, cnd modulele din cadrul sistemului sunt dezvoltate independent de catre programatori diferiti. Pe o scara mai mica, editoarele din aceste pachete integrate sunt adesea adaptiv limbajului de programare folosit. De exemplu, un astfel de editor va oferi de regula modul de in dentare care reprezinta standardul de facto al limbajului tinta, iar n unele cazuri va recunoaste si va completa automat cuvintele cheie dupa scrierea primelor caractere ale acestora. Unele pachete integrate au trecut chiar de etapa editoarelor clasice, devenind sisteme grafice de interfata si permitnd construirea programelor pe baza unor blocuri prefabricate, reprezentate ca pictograme si selectate de programator n functie de necesitati, n timpul crearii programului. Aceste pachete marcheaza o noua etapa n continua evolutie a procesului de programare. Aceasta pare sa fie tendinta: construirea produselor software nu se va mai face prin scrierea programului instructiune cu instructiune, ci prin combinarea unor blocuri prefabricate de dimensiuni relativ m ari. 4. CALCUL PARALEL n domeniul limbajelor de programare se afla n plina expansiune o ramura care se ocupa de dezvoltarea limbajelor pentru descrierea proceselor ce se executa simultan. De fapt, aceste procese se pot desfasura ntr-adevar simultan, pe mai multe procesoare (ntr-un mediu multiprocesor), sau pot doar sa dea iluzia simultaneitatii (n sistemele cu partajare n timp). Sa luam ca exemplu un program de prognoza meteo, care se bazeaza pe un model al atmosferei compus din doua niveluri. Unul dintre procese ar putea avea sarcina de a prezice conditiile din atmosfera nalta (cum ar fi directia si viteza fronturilor atmosferice), n timp ce celalalt proces s ar ocupa de prognoza pentru atmosfera joasa. Desigur, cele doua procese nu pot fi complet independente, ci trebuie sa comunice ntre ele. n acest scop, sistemul ar putea fi proiectat astfel nct fiecare proces sa nceapa n mod independent, elabornd prognozele respective pentru un interval de o ora, iar dupa aceea sa-si mpartaseasca predic tiile si pe baza lor sa elaboreze n mod independent prognozele pentru urmatorul interval de o ora. n acest fel, cele doua procese ar putea elabora prognoze pentru 24 de ore coordonndu-si eforturile n 24 de pasi. Pentru a scrie programele corespunzatoar e unor astfel de aplicatii de calcul paralel, limbajele respective trebuie sa permita exprimarea activitatilor de coordonare a diferitelor procese din cadrul sistemului. n unele cazuri, aceste facilitati au fost ncorporate n limbaj ca primitive; n altele, ele sunt implementate ca extensii ale unui limbaj existent. Ada este unul dintre limbajele care intra n prima categorie; de altfel, obtinerea unui limbaj pentru exprimarea programelor utilizate n medii cu prelucrare paralela a fost unul dintre principalele obiective fixate la proiectarea limbajului. Un exemplu de extensie de limbaj este ansamblul de caracteristici cunoscut sub numele de Linda. Linda nu este un limbaj de programare, ci o serie de primitive care adaugata la un limbaj existent conduce la obtinerea unui limbaj extins, care permite calculul paralel. Cu Linda, cercetatorii au creat si au experimentat extensii paralele ale unor limbaje cunoscute, cum ar fi C, FORTRAN, LISP, Pascal si Prolog. Ideea centrala este aceea a unei zone partajabile d stocare, numita spatiul tuplurilor, n care e fiecare proces din sistem poate depozita sau regasi grupuri de date numite tupluri. Orice proces poate
50

depozita aici un tuplu n orice moment, si de asemenea poate oricnd ncerca sa elimine un anumit tuplu, cu observatia ca daca ncearca sa elimine un tuplu inexistent, va trebui sa astepte pna cnd alt proces depoziteaza un tuplu cu proprietatile respective. Un tuplu este un ansamblu format din unul sau mai multe elemente de date asezate ntr-o anumita ordine. Cel mai adesea, tuplurile se reprezinta ca o lista de date incluse ntre paranteze. Astfel, tuplul care contine valorile 5, 3.2 si Fred se scrie
(5, 3.2, Fred)

si, datorita ordinii, este diferit de tuplul


(3.2, Fred, 5)

Pentru exprimarea operatiilor elementare de depozitare si extragere a tuplurilor din zona comuna, Linda furnizeaza niste primitive cu numele in si out. Primitiva in este utilizata pentru recuperarea unui tuplu din spatiul de tupluri, iar out pentru depozitarea unui tuplu. Termenii in (nauntru) si out (n afara) exprima asadar sens transferului fata de procesul, nu fata de spatiul de tupluri. Astfel, primitiva out este utilizata pentru a deplasa un tuplu n afara procesului si a-l depune n spatiul de tupluri, iar in pentru a aduce un tuplu din spatiul comun ntr-un anumit proces (dupa cum se vede n figura 3.14). De exemplu, instructiunea
out (5, 17)

va fi utilizata de proces pentru a depozita tuplul (5, 17) n spatiul comun, instructiunea
in (5, 17)

pentru a recupera acest tuplu. Pentru a salva componente ale unui tuplu extras se pot folosi variabile precedate de un semn de ntrebare. De exemplu, daca Value este o variabila de tip ntreg, atunci instructiunea
in ("final cost", ?Value)

va avea ca efect recuperarea oricarui tuplu care are ca prima componenta sirul de caractere final cost si ca a doua componenta un ntreg, valoarea ntregului din tuplul selectat fiind atribuita variabilei Value. Daca nu exista un astfel de tuplu, atunci procesul va trebui sa astepte pna la depozitarea unui , n a momentul n care un astfel de tuplu este n fine depozitat n spatiul comun, el va fi de ndata eliminat, variabila Value va lua valoarea corespunzatoare, iar procesul va putea continua.

Figura 3.14 Directiile de miscare ale tuplurilor asociate primitivelor in si out De observat ca operatiile in si out trebuie implementate ca rutine atomice; cu alte cuvinte, fiecare dintre ele trebuie sa reprezinte o entitate indivizibila. ntr-adevar, daca un proces ncepe o operatie in si gaseste un tuplu de tipu l dorit, trebuie sa i se permita sa recupereze tuplul respectiv nainte ca acesta sa fie gasit si de alt proces; nu uitati ca ntr-un mediu multiprocesor mai multe procese pot cotrobai n spatiul tuplurilor n acelasi timp. Figura 3.15 ilustreaza modul n care poate fi exprimat exemplul nostru referitor la prognoza meteo daca extindem pseudocodul astfel nct sa includa primitive Linda. Cele doua procese sunt reprezentate prin procedurile LowLevel si HighLevel. Dupa ce si elaboreaza prognoza pentru un interval de o ora, procedura LowLevel si depune tuplul ("low-level done") n spatiul comun si ncearca sa recupereze tuplul ("high-level done"); daca nu-l gaseste,
51

va fi fortata sa astepte. La rndul ei, procedura HighLevel si elaboreaza propria prognoza pentru un -l interval de o ora si depoziteaza n spatiul comun tuplul asteptat de procesul LowLevel. Din acest punct, cele doua procese si continua elaborarea prognozelor pentru urmatorul interval de o ora. Observati ca rezultatele obtinute de fiecare proces n parte pot fi comunicate prin includerea lor n tuplurile generate. n ncheiere, vom face o lista a celorlalte primitive Linda disponibile n marea majoritate a implementarilor. Prima dintre ele este rd (prescurtare de la read - citire care este similar a cu in, cu exceptia faptului ca nu elimina tuplul din spatiul comun, ci doar l citeste. Este utilizata n principal pentru a permite mai multor procese sa detecteze simultan prezenta n spatiul comun a unui anumit tuplu. Primitivele inp si rdp sunt sim ilare cu in si rd, cu diferenta ca nu obliga procesul sa astepte aparitia tuplului cautat. n sfrsit, primitiva eval este utilizata pentru a initia executia proceselor care se desfasoara n paralel. De exemplu, pentru a initia procesul de elaborare a prog nozei meteo am putea folosi instructiunile
eval (LowLevel) eval (HighLevel) procedure LowLevel assign Count the value 1; while (Count ? 24) do (Pregateste prognoza pentru atmosfera joasa, pentru urmatorul interval de o ora; out ("low-level done"); in ("high-level done"); assign Count the value Count + l) procedure HighLevel assign Count the value 1; while (Count ? 24) do (Pregateste prognoza pentru atmosfera nalta, pentru urmatorul interval de o ora; out ("high-level done"); in ("low-level done"); assign Count the value Count +1

Figura 3.15 O reprezentare n pseudocod a programului de elaborare a prognozei meteo

52

S-ar putea să vă placă și