Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateC
C sharpCalculatoareCorel drawDot netExcelFox pro
FrontpageHardwareHtmlInternetJavaLinux
MatlabMs dosPascalPhpPower pointRetele calculatoare
SqlTutorialsWebdesignWindowsWordXml

LIMBAJE DE PROGRAMARE

calculatoare



+ Font mai mare | - Font mai mic



LIMBAJE DE PROGRAMARE

PERSPECTIVE ISTORICE

Primele generatii



La inceput, programarea presupune o metoda foarte laborioasa, anume transpunerea algoritmilor respectivi in limbaj-masina, suplimentar fata de proiectarea algoritmului. Dupa localizarea si corectarea erorilor, se poate spune ca programul este utilizabil.

Prima simplificare a procesului de programare a fost sa se renunte la reprezentarea operatiilor si operatorilor sub forma de cifre hexazecimale, atribuindu-se memoria pentru instructiunile limbajului-masina. In cazul operanzilor s-au stabilit reguli pentru atribuirea unor nume descriptive (identificatori) pentru locatiile de mnemonice si utilizarea acestor nume in instructiuni.

Initial programatorii foloseau aceste notatii pentru dezvoltarea programului pe hartie, ulterior translatandu-l intr-o forma utilizabila de calculator. Procesul de translatare este un tip de activitate care poate fi realizata direct de calculator. Utilizarea mnemonicelor s-a oficializat ca limbaj de asamblare, s-a creat asamblorul, care translateaza programele scrise in limbaj de asamblare intr-o forma compatibila cu calculatorul.

Limbajele de asamblare au aparut ca un pas urias pe drumul catre medii de programare mai eficiente.

Limbajele de asamblare, ca limbaje de generatia a doua, prezentau multe avantaje fata de limbajele-masina (prima generatie), dar nu constituiau un mediu de programare foarte propice.

Orice limbaj de asamblare este dependent de masina, deoarece instructiunile folosite se refera la caracteristicile unui anumit calculator.

Alt dezavantaj al limbajelor de asamblare este acela ca programul trebuie gandit la un nivel foarte coborat (instructiunile urmaresc pas cu pas limbajul-masina), in loc sa se concentreze asupra unei solutii globale a problemei de rezolvat.

Pe baza acestor concepte s-au dezvoltat limbaje de programare, din a treia generatie, la care primitivele erau de nivel inalt si independente fata de masina (calculator). Principala preocupare in dezvoltarea limbajelor de programare din generatia a treia a fost

identificarea unui ansamblu de primitive de nivel inalt, similare pseudocodului despre care am discutat, care sa permita dezvoltarea produselor software. Dupa identificarea setului de primitive la nivel inalt, a fost scris un program, numit translator, care translateaza programele exprimate in primitive de nivel inalt in programe in limbaj-masina. Aceste programe de translatare au ajuns sa fie cunoscute sub denumirea de compilatoare.

Independenta fata de masina

Un program scris intr-un limbaj din generatia a treia poate fi utilizat la orice calculator, utilizand pur si simplu asupra lui compilatorul corespunzator.

O componenta a problemei portabilitatii este faptul ca in unele cazuri nu s-a ajuns la un acord cu privire la definitia corecta (exacta) a unui anumit limbaj. Pentru a elimina probleme de acest tip, American National Standards Institute (ANSI) si International Standars Organization (I S O) au adoptat si publicat standarde pentru multe din limbajele cele mai raspandite.

Faptul ca masinile pot acum sa raspunda la instructiuni de nivel inalt a permis specialistilor sa vizeze medii de programare in care oamenii sa poata sa comunice cu masina direct prin intermediul unor concepte abstracte specifice gandirii umane, fara sa mai fie necesara transpunerea intr-o forma compatibila masinii.

De asemenea, exista preocupari pentru realizarea unor masini (calculatoare) care sa participe nu numai la executia algoritmilor, ci si la dezvoltarea algoritmilor. Rezultatul acestor preocupari a condus la aparitia unei game de limbaje de programare in continua diversificare, care cu greutate pot fi clasificate in generatii.

Ca regula generala, termenul de limbaje de programare din generatia a patra se refera la pachetele software care permit utilizatorilor fara o pregatire de specialitate sa poata adapta produsele propriilor lor necesitati. In aceasta categorie se incadreaza sistemele de calcul tabelar, sistemele de baze de date, pachete pentru grafica, procesoare de text, aceste pachete sunt adesea grupate intr-un singur sistem integrat.

Termenul de limbaje din generatia a cincea este folosit adesea cu referire la programarea declarativa si in special pentru ceea ce se numeste programarea logica.

Paradigme de programare

Dezvoltarea istorica a limbajelor de programare se poate

reprezenta printr-o diagrama cu mai multe piste, in care caile de dezvoltare (conform diferitelor paradigme) sunt reprezentate separat (fig. 3.1). Apar astfel patru piste care ilustreaza patru paradigme diferite: functionala, orientata spre obiecte, imperativa, declarativa, limbajele asociate fiecaruia fiind infatisate intr-un mod care sa arate evolutia lor in timp, ceea ce nu inseamna ca aceste limbaje au evoluat neaparat unele din altele.

LISP KL Scheme

Functionale

SIMULA C++ Ada 95 _____ Orientate Smaltalk Java spre obiecte

Limbaje FORTRAN BASIC C Ada

Imperative masina COBOL ALGOL APL Pascal

GPSS Prolog

Declarative

Fig. 3.1. Evolutia paradigmelor de programare

Paradigma imperativa (procedurala) reprezinta modul clasic ce abordare a procesului de programare. Pe aceasta paradigma se bazeaza ciclul parcurs de unitatea centrala: citirea instructiunii - decodificare - executie. Prin aceasta paradigma se defineste procesul de programare ca o secventa de comenzi care, urmate, conduc la rezultatul dorit.

Paradigma declarativa propune dezvoltarea si implementarea unui algoritm general de rezolvare a problemelor. Pentru rezolvarea unei probleme nu va trebui decat ca ea sa fie formulata intr-o maniera compatibila cu algoritmul si sa i se aplice algoritmul respectiv.

Principalul obstacol in calea dezvoltarii unui limbaj de programare bazat pe paradigma declarativa este descoperirea algoritmului (general) de rezolvare a problemelor.

Paradigma functionala prezinta procesul de dezvoltare a programelor ca o constructie de "cutii negre", fiecare acceptand intrari si furnizand iesiri.

Matematicieni desemneaza aceste "cutii" drept functii, de unde denumirea de paradigma functionala.

Primitivele unui limbaj de programare functional constau din functii elementare de baza cu care programatorul construieste functiile complexe necesare rezolvarii problemei respective.

Paradigma de programare functionala incurajeaza abordarea

modulara a programelor, deci programele sunt bine organizate in mod natural. Cu aceasta metoda se dezvolta de obicei pachete de software complexe.

Paradigma orientata spre obiecte

Aceasta metoda conduce la un proces de programare cunoscut sub numele de programare orientata spre obiecte (OOP - object oriented Programming). In aceasta abordare datele sunt considerate a fi obiecte "active", spre deosebire de rolul pasiv care le este atribuit in paradigma imperativa.

In abordarea orientata pe obiecte lista e considerata a fi un obiect care se compune din lista propriu-zisa, la care se adauga un ansamblu de rutine pentru gestionarea ei. Programul care lucreaza cu lista nu are nevoie de algoritmi pentru efectuarea acestor operatii, ci foloseste rutinele oferite de obiect. Limbajele de programare orientate spre obiecte sunt Visual Basic (Microsoft Corporation) si Delphi (Borland International).

2. CONCEPTELE PROGRAMARII CLASICE

In principiu, instructiunile intr-un limbaj de programare se impart in: instructiuni declarative, instructiuni imperative si comentarii.

Instructiunile declarative definesc terminologia specifica utilizata in cadrul programului (ex. numele folosite pentru diferite date). Instructiunile imperative sunt cele care descriu pasii algoritmului respectiv. Comentariile imbunatatesc intelegerea algo-ritmului.

Orice modul de program incepe cu o parte declarativa (descrierea terminologiei), urmata de o parte procedurala (instructiuni imperative pentru indicarea actiunilor). Comentarii sunt plasate in program ori de cate ori se considera necesar acest lucru.

Variabile, constante si literali

Identificatori de tip nume descriptive a unor locatii de memorie sunt cunoscuti sub numele de variabile. Prin modificarea valorii stocate in locatia respectiva in timpul executiei programului se schimba valoarea asociata identificatorului.

Uneori programul foloseste valori predefinite care nu se modifica. Aceasta valoare se poate include ca un literal.

Unele limbaje de programare permit atribuirea de nume descrip-

tive si unor valori particulare care nu pot fi modificate. Aceste nume se numesc constante.

Ex

Pentru scrierea unui program referitor la un aeroport este necesara altitudinea acestuia. Intr-o linie de program ce utilizeaza literali aceasta se scrie astfel:

assign Effective Alt the value (Altimeter - 392)

unde: Effective Alt, Altimeter sunt variabile,

este o valoare literala.

Intr-o linie de program ce utilizeaza constante acelasi lucru se scrie astfel:

assign Effective Alt the value (Altimeter -Airpor Alt)

const Aieport Alt

(instructiunea declarativa const asociaza constanta AirporAlt cu valoarea 392, iar numele Airpot Alt poate fi folosit oriunde in program in locul valorii 392).

Tipuri de date

Instructiunile declarative identifica si tipul datelor. Tipul datelor determina modul in care este interpretat sirul respectiv de biti, cat si operatiile care pot fi efectuate cu data respectiva. Cele mai utilizate tipuri de date sunt: intreg (integer), real (real), caracter (character) si boolean.

Tipul integer se refera la date numerice intregi, reprezentate in complement fata de doi. Se pot efectua cu aceste numere operatii aritmetice clasice si comparatiile.

Tipul real se refera la numere reale, stocate in general in virgula mobila. Activitatile care trebuie executate pentru adunarea a doua numere reale sunt diferite de cele pentru adunarea doi intregi.

Tipul character se refera la date care constau din simboluri, codificate de obicei in ASCII. Asupra acestui tip de date se pot efectua: comparatii asupra pozitionarii alfabetice a unui simbol fata de altul; testarea aparitiei unui sir de simboluri in cadrul altui sir, concatenarea unui sir de simboluri la sfarsitul altuia pentru a forma un sir de mai lung.

Tipul boolean se refera la acele date cu valori doar de adevarat sau fals, ce apar ca urmare a efectuarii unor comparatii. Operatiile compatibile cu acest tip de date sunt verificarile daca o valoare este adevarata sau falsa.

In figura 3.2 sunt prezentate exemple de astfel de instructiuni

declarative in Pascal, C, C++, Java si FORTRAN. In aceste exemple variabilele Length si Width sunt declarate de tip real, iar Price, Tax,

Total de tip intreg.

Declaratii de variabile in Pascal:

Var

Length, Width: real;

Price, Tax, Total : integer.

Declaratii de variabile in C, C++ si Java:

float Length, Width;

int Price, Tax, Total.

Declaratii de variabile in FORTRAN:

REAL Length, Width;

INTEGER Price, Tax, Total.

Fig. 3.2. Declaratii de variabile in Pascal, C, C++, Java, FORTRAN

Structuri de date

Un concept asociat instructiunilor declarative este acela de structura de date care se refera la forma conceptuala a datelor.

Datele pe langa tip, deja explicat in capitolul anterior, au si o lungime (marime).

Un sir de caractere este un caz particular al unei structuri generice de date care poarta numele de vector omogen (homogeneous array).

Pentru a declara un astfel de vector, majoritatea limbajelor de programare utilizeaza o instructiune declarativa in care se precizeaza marimea pentru fiecare dimensiune a vectorului.

In fig. 3.3 se prezinta instructiuni declarative in C si Pascal care declara Nume ca vector unidimensional de tip caracter si lungime opt, iar Scores ca vector bidimensional de tip intreg, cu doua linii si noua coloane.

Vectori declarati in pascal

Var

Name: packet array [18] of char;

Scores: array [12, 19] of integer.

Vectori declarati a C

char Name [8];

int Scores [2] . [9].

Structura conceptuala a vectorilor

Name:

Scores:

Fig. 3.3. Declararea unor vectori omogeni in Pascal si C

Exista si vectori neomogeni, din punct de vedere al tipului de date incluse, numiti vectori heterogeni (heterogenous array). In fig. 3.4 se prezinta modul de declarare a unui asemenea vector.

Dupa declararea vectorului se poate face referire la el in intregime, prin nume, iar la fiecare componenta a sa prin pozitia acesteia. In cazul vectorilor omogeni componentele sunt identificabile prin indici care specifica linia, coloana etc.

Vectori declarati in Pascal

Var

Employe: record

Name: packed array [18] of char;

Age : integer;

Skill Rating: real

end

Vectori declarati in C

Struct

(char Name [8];

int Age ;

float Still Rating;

Employe

Organizarea conceptuala a vectorului

Employer


Name Age SkillRating

Fig. 3.4. Declararea unor vectori heterogeni in Pascal si C

Instructiuni de atribuire

Instructiunea de atribuire solicita ca unei variabile sa i se atribuie o valoare. O astfel de instructiune are urmatoarea sintaxa: variabila urmata de un simbol care reprezinta operatia de atribuire si d e o expresie care indica valoarea ce se atribuie.

In limbajele C, C++ instructiunea

Total = Price + Tax

cere ca variabilei Total sa-i fie atribuita valoarea sumei dintre Price si Tax.

In paradigmele imperativa si cea orientata pe obiecte instruc-

instructiunea de atribuire este foarte utilizata, deoarece datele sunt manipulate in principal prin intermediul sau.

Instructiuni de control

Instructiunile de control sunt instructiuni imperative care modifica ordinea de executie a programului. Aceste instructiuni au starnit cele mai multe controverse, iar "principalul vinovat" este cea mai simpla dintre ele, "go to". Aceasta instructiune furnizeaza o metoda de a continua programul din alt punct, care a fost identificat printr-o eticheta (nume, numar). Includerea unei astfel de instructiuni intr-un limbaj de nivel inalt conduce la scrierea unor secvente foarte incalcite. Pentru evitarea unor asemenea situatii, limbajele moderne de programare dispun de instructiuni de control mai elaborate (ex. if - then - else) care permit ramificarea programului prin intermediul unei singure structuri sintactice.

In figura 3.5 sunt prezentate cateva din cele mai utilizate structuri de ramificare si instructiuni de control, precum si modul lor de reprezentare in diverse limbaje.

Pascal C, C++, Java

if B then S1 if B S1

else S2 else S2

Adevar B ? Fals

A d a

S 2

 

S 1

 
if B then S1

else S2

end if

Pascal C, C++, Java

while B do while B

S1; S1;

Fals B ?

Adevar A d a

S 1

 
while B loop

S1

end loop;

Pascal C, C++, Java

case N of Switch (N)

C1 : S1; ( case C1 : S1; C2 : S2; case C2 : S2;

Care este C3 : S3; case C3 : S3; valoarea end; );

lui N ?

A d a case N is

N = C1 N = C2 N = C3 when C1 S1;

S 3

 

S 2

 

S 1

 
when C2 S2; when C3 S3 ;

end case

Fig. 3.5. Structuri de control si reprezentarea lor in Pascal, C, C++, Java si Ada

O alta structura larg folosita este cea numita for. Ea este similara cu structura while utilizata in pseudocod, dar initializarea, modificarea si incheierea ciclului sunt incorporate intr-o singura instructiune.


Atribuie lui Count

valoarea 1


Fals

Count < 4?

Adevar

  Atribuie lui Count

Corpul buclei valoarea Count + 1

Pascal C, C++, Java

for Count : = 1 to 3 do for (Count = 1; Count < 4; ++ Count)

begin (body)

body

end.

Fig. 3.6. Structura for si reprezentarea ei in Pascal, C, C++ si Java

Comentarii

Experienta arata ca oricat de bine ar fi proiectat un limbaj de

programare si oricat de bine ar fi folosit, informatiile suplimentare sunt utile intotdeauna pentru orice doritor care incearca sa inteleaga un program de oarecare complexitate. In acest scop limbajele de programare furnizeaza o sintaxa pentru inserarea in program a unor instructiuni explicative numite comentarii. Documentarea constituita din aceste comentarii se numeste documentatie interna

Documentatia interna este ignorata de catre translator. pentru a include comentariile in program, limbajele de programare furnizeaza doua metode de delimitare a acestora de restul programului. Fie se include comentariul intre niste marcaje speciale, fie se marcheaza doar inceputul comentariului, acesta urmand sa ocupe tot randul sau chiar mai multe randuri (in acest caz se adauga si la inceputul randurilor suplimentare semnul specific comentariului. Este recomandabil ca toate comentariile care se refera la un anumit modul de program sa fie grupate intr-un singur loc.

3. MODULE DE PROGRAM

Limbajele bazate pe paradigma functionala impart in mod natural programele in functii, iar limbajele bazate pe paradigma orientata spre obiecte au ca rezultat module de program care reprezinta obiectele.

Ne vom concentra asupra tehnicilor prin care se poate obtine o reprezentare modulara a unui algoritm.

Proceduri

Procedura este un modul de program scris indepndent de programul principal, dar legat de acesta printr-un proces de transfer/revenire conform fig. 3.

Model

apelant

 

Procedura

  Transfer


Revenire

Fig. 3. Transferul controlului la apelarea unui subprogram

Cand este nevoie de serviciile procedurii, controlul se transmite acesteia (instructiunea JUMP, limbajul-masina), iar dupa executie controlul revine modulului principal.

Ca regula generala, variabilele declarate in interiorul procedurii sunt variabile locale (se utilizeaza numai in interiorul procedurii). Sunt totusi cazuri in care unele date trebuie utilizate in comun de mai multe module. Variabilele utilizate intr-o asemenea situatie se numesc variabile globale.

Parametrii

Folosirea in comun a unor informatii prin utilizarea unor variabile globale nu este recomandata, deoarece acest mod de lucru mascheaza activitatile modulelor de program care partajeaza datele respective.

Se recomanda identificarea datelor partajate de mai multe module de program, ceea ce se poate face prin includerea explicita a listei acestora in instructiunea prin care se solicita executia procedurii. Astfel si antetul procedurii trebuie sa contina o lista a variabilelor carora li se atrib7uie valori la apelarea procedurii. Elementele care compun aceste doua liste se numesc parametri.

La apelarea procedurii, lista de parametri din modulul apelant este asociata, element cu element, listei de parametri din antetul procedurii. Valorile parametrilor din modulul apelant sunt transferate efectiv parametrilor corespondenti din procedura.

Dupa aceea, procedura este executata, iar valorile (eventual modificate) sunt transferate inapoi catre modulul apelant. In alte situatii transferul poate avea loc intr-un singur sens, fie catre procedura, fie catre modulul apelant.

Un avantaj major al acestui sistem de substituire este acela ca aceeasi procedura poate fi apelata de mai multe ori, cu diferite seturi de date.

F u n c t i i

Termenul de functie se refera la un modul de program asemanator unei proceduri, cu deosebirea ca o valoare se transfera inapoi catre programul principal nu prin intermediul listei de parametri, ci ca "valoare a functiei". Altfel spus, valoarea respectiva este asociata numelui functiei, asa cum se asociaza o valoare unei variabile. In cazul functiei, valoarea se obtine prin executarea instructiunilor din cadrul functie.

Instructiuni de intrare/iesire

Procedurile si functiile sunt metode foarte bune de a extinde caracteristicile unui limbaj de programare.

Daca limbajul nu furnizeaza o anumita operatie ca primitiva, se poate scrie o procedura sau o functie care sa efectueze acea operatie, iar apoi se va apela la modulul respectiv ori de cate ori este nevoie. In majoritatea limbajelor, operatiile de intrare/iesire sunt implementate in acest mod, cu diferenta ca procedurile si functiile apelate sunt de fapt rutine ale sistemului de operare.

Pentru a citi o valoare de la tastatura si a o atribui variabilei Value, in Pascal se scrie:

readln (Value)

iar pentru a afisa valoarea respectiva pe ecran:

writeln (Value)

Limbajul C++, fiind un limbaj orientat pe obiecte, furnizeaza doua obiecte prefabricate, cin si cout, care reprezinta dispozitivul standard de intrare si, respectiv, dispozitivul standard de iesire. Aceeasi actiune de mai sus in limbajul C++ se va scrie astfel:

cin >>Value; [citirea valorii de la tastatura]

cout << Value; [afisarea variabilei Value pe ecran].

4. IMPLEMENTAREA LIMBAJELOR

In continuare vom analiza procesul de convertire a unui program scris intr-un limbaj de nivel inalt intr-o forma executabila de masina.

Procesul de translatare

Procesul de convertire a unui program dintr-un limbaj in altul se numeste translatare. Programul in 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.

Analizor Analizor Generator

lexical sintactic de cod

Analiza Analiza Generarea

lexicala sintactica codului

Program sursa Program obiect

Fig. 3.8. Procesul de translatare

Analiza lexicala este procesul prin care se identifica sirurile de simboluri din programul sursa are reprezinta entitatile distincte. Pe masura ce analizorul lexical identifica grupuri de simboluri care constituie entitati distincte, le clasifica in functie de ceea ce reprezinta - o valoare numerica, un cuvant, un operator aritmetic, ¾ si genereaza un model de biti cunoscut sub numele de simbol (token), care arata clasa entitatii respective.

Analiza sintactica este un proces de identificare a structurii gramaticale a programului si de recunoastere a rolului fiecarei componente. Majoritatea limbajelor de programarea sunt limbaje cu format liber, ceea ce inseamna ca locul instructiunilor in program nu are importanta. Pentru ca un calculator sa poata analiza sintactic un program scris intr-un limbaj cu format liber trebuie ca analizorul sa-l identifice indiferent de spatiile utilizate in programul sursa.

In acest scop majoritatea limbajelor folosesc semnele de punctuatie, cum ar fi punct si virgula, pentru a marca sfarsitul unei instructiuni, precum si de cuvinte-cheie (cuvinte rezervate), cum ar fi if, then sau else pentru a marca inceputul unor propozitii distincte.

Procesul de analiza sintactica se bazeaza pe un set de reguli care definesc sintaxa limbajului de programare, reprezentare prin diagramele de sintaxa. In fig. 3.9 se prezinta diagrama de sintaxa a instructiunii if - then - else.

Expresie

if then Instructiune else Instructiune

booleana

Fig. 39. Diagrama de sintaxa a instructiunii if - then - else din pseudocod

Procesul de analiza sintactica consta, in esenta, din construirea arborelui de analiza sintactica a programului sursa. Din acest motiv, regulile de sintaxa care descriu structura gramaticala a unui program nu trebuie sa permita obtinerea a doi arbori diferiti pentru acelasi sir analizat.

Pentru exemplificare, regula din fig. 3.9 contine o eroare care permite ca, pentru instructiunea :

if B1 if B2 then S1 else S2

sa se obtina doi arbori de analiza diferiti, prezentati in fig. 3.10.

Instructiune

 


if Expresie then Instructiune else Instructiune

booleana

(B1) (S2)

if Expresie then Instructiune

booleana

(B2) (S1)

Instructiune

if Expresie then Instructiune

booleana

(B1)

if Expresie then Instructiune else Instructiune

booleana

(B2) (S1) (S2)

Fig. 3.10. Arbori de analiza sintactica diferiti pentru instructiunea

( if B1 then if B2 then S1 else S2 )

Definitiile de sintaxa ale limbajelor formale de programare sunt proiectate astfel incat sa evite asemenea ambiguitati, folosind parantezele. Pentru a distinge cele doua interpretari posibile vom scrie:

if B1

then (if B2 then S1)

else S2

if B1

then (if B2 then S1

else S2)

Informatiile extrase din instructiunile declarative sunt inregistrate intr-o tabela numita tabela de simboluri, care contine date referitoare

la variabilele care au fost declarate si la tipurile si structurile de date asociate.

O alta activitate din cadrul translatarii unui program este generarea codului, reprezentand procesul de construire a instructiunilor in limbajul-masina care simuleaza instructiunile recunoscute de analizorul sintactic. Una din sarcinile importante ale generatorului de cod este optimizarea codului.

Analiza lexicala, sintactica si generarea codului nu se realizeaza strict in aceasta ordine, ci se impletesc: analizorul lexical identifica primul simbol si il transfera analizorului sintactic care ar trebui sa urmeze si ii cere urmatorul simbol.

In momentul in care sunt recunoscute instructiuni sau propozitii complete, analizorul sintactic apeleaza generatorul de cod, care produce instructiunile masina necesare.

Editarea de legaturi si incarcarea

Programul obiect care rezulta in urma procesului de translatare, desi exprimat in limbaj masina, este arareori intr-o forma executabila. Majoritatea mediilor de programare permit dezvoltarea si translatarea individuala a modulelor de program, la momente diferite, ceea ce permite constructia modulara a produselor software. Chiar daca programul este dezvoltat si translatat sub forma unui singur modul, in cele mai multe cazuri programul obiect tot nu este pregatit pentru executie, deoarece contine cereri de servicii software care sunt oferite direct de sistemul de operare sau pot fi obtinute prin intermediul acestuia.

Un program obiect este un program masina caruia ii lipsesc unele legaturi care trebuie "innodate" pentru a-l transforma intr-un program executabil.

Innodarea acestor legaturi este efectuata de un program numit editor de legaturi (linker). Sarcina acestui linker este de a lega intre ele programele-obiect, rutinele sistemului de operare si alte utilitare software intr-un program executabil (modul incarcabil), memorat ca fisier in sistemul de stocare de masa al calculatorului.

Pentru executarea unui program astfel translatat, el trebuie plasat in memorie de catre programul de incarcare (leader), parte a secventiatorului.

Pe scurt, pregatirea unui program scris intr-un limbaj de nivel inalt consta dintr-o secventa de trei pasi: translatare, editare de legaturi si incarcare, asa cum se vede in fig. 3.11. Dupa translatare si editare de legaturi, programul poate fi incarcat si executat in mod repetat, fara a mai reveni la versiunea-sursa. Daca sunt necesare modificari in program, acestea se fac in programe-sursa, dupa care sursa modificata este translatata si se face editarea de legaturi, obtinandu-se un nou model incarcabil.

Program Program Editare Modul de Program

sursa Translatare obiect de incarcare Incarcare executabil

legaturi

Fig. 3.11. Procesul complet de pregatire a programului

Pachete pentru dezvoltarea produselor software

Tendinta curenta este aceea de a grupa translatorul si celelalte elemente software utilizate in procesul de dezvoltare a unui produs software intr-un pachet care functioneaza ca un sistem integral. Avantajele utilizarii unui astfel de sistem integrat sunt reprezentate de posibilitatea ca programatorul sa poata trece cu usurinta de la editor la instrumente de depanare modificand si testand imediat programul.

5. PROGRAMAREA DECLARATIVA

Logica formala furnizeaza un algoritm general de rezolvare a problemelor, in jurul caruia se poate construi un sistem de programare declarativa.

Deductia logica

Sa presupunem ca urmatoarea afirmatie este adevarata: Kermit fie este bolnav, fie se afla pe scena.

In aceste conditii, daca ni se spune despre Kermit ca nu este pe scena, tragem concluzia ca este bolnav.

Acesta este un exemplu de aplicare a principiului deductiv numit rezolutie.

Ca sa intelegem mai bine acest principiu, sa incepem prin a reprezenta propozitiile logice prin litere, iar negarea negatiile lor prin simbolul "¾" insotit de o litera.

In forma generala principiul rezolutiei precizeaza faptul ca daca propozitiile:

P OR Q si R OR ¾ Q

sunt adevarate, atunci si propozitia:

P OR R

este adevarata.

Altfel spus, cele doua propozitii initiale se rezolva prin a treia, numita rezolvent.

Se observa ca rezolutia poate fi aplicata doar perechilor de propozitii cu forma clauzala (propozitii legate prin operatorul boolean OR).

In fig. 3.12 vom reprezenta grafic rezolutia a doua propozitii.

P OR Q R OR ¾ Q

P OR R

Fig. 3.12. Rezolvarea propozitiilor (P OR Q) si (R OR -Q) prin (P OR Q)

Se spune ca o serie de propozitii este inconsistenta daca este imposibil ca toate propozitiile sa fie adevarate in acelasi timp.

In fig. 3.13 se demonstreaza faptul ca setul de propozitii P OR Q; R OR ¾ Q; ¾ R; ¾ P este inconsistent.

P OR Q R OR ¾ Q ¾ R ¾ P


P OR R


P


Propozitie nula

Fig. 3.13. Rezolvarea propozitiilor (P OR Q) si (R OR ¾ Q), ¾ R si ¾ P

Procesul prin care, pentru a face posibila aplicarea principiului rezolutiei variabilelor, li se atribuie valori se numeste unificare.

Acest proces, de unificare, permite ca intr-un sistem deductiv propozitiile generale sa fie aplicate in cazuri particulare.

Limbajul PROLOG

Limbajul Prolog (PROgramming in LOGic) este un limbaj de programare declarativa al carui algoritm de rezolvare a programelor are la baza rezolutia repetata.

Un program Prolog consta dintr-o serie de propozitii initiale, pe care algoritmul isi bazeaza toate deductiile.

Componentele din care sunt construite aceste propozitii se numesc predicate. Un astfel de predicat se compune dintr-un identificator, urmat de o paranteza cu lista argumentelor predicatului.

Argumentele predicatului incep intotdeauna cu litera mica. Limbajul Prolog face distinctia intre constante (litera mica) si variabile (majuscule).

Instructiunile intr-un limbaj Prolog sunt fie afirmatii, fie reguli; ele se termina cu punct.

O afirmatie consta dintr-un singur predicat.

Nu trebuie sa va inchipuiti ca sistemul Prolog intelege semnificatia predicatelor din program; el le manipuleaza intr-o maniera absolut simbolica, aplicand regulile de inferenta ale rezolutiei.

Programatorului ii revine responsabilitatea de a descrie toate caracteristicile si predicatele sub forma unor afirmatii si reguli.

Majoritatea implementarilor de Prolog sunt proiectate pentru utilizare interactiva.

Atunci cand sistemul Prolog primeste o intrebare, el ii aplica principiul rezolutiei incercand sa confirme faptul ca o afirmatie corespunzatoare intrebarii este o consecinta a afirmatiilor initiale.

Astfel, pe baza seriei de instructiuni care descriu viteza relativa, pot fi confirmate toate intrebarile urmatoare:

faster (broasca, melc)

faster (iepure, broasca)

faster (iepure, melc).

Primele doua sunt afirmatii care apar in setul initial de instructiuni, iar cea de a treia poate fi dedusa de catre sistem.

Daca furnizam sistemului intrebari care au argumente variabile, nu constante, vom obtine exemple mult mai interesante.

De exemplu, pornind de la intrebarea:

faster (w, melc)

vom obtine ca raspuns

faster (broasca, melc).

Putem cere sistemului Prolog sa gaseasca animale care sunt mai lente decat iepurele punandu-i intrebarea:

faster (iepure, w).

Astfel, utilizand un singur program Prolog, vom putea sa confirmam faptul ca un animal este mai rapid decat altul, sa gasim toate animalele care sunt mai rapide decat un animal dat sau sa gasim toate relatiile dintre animale in ceea ce priveste viteza.

Aceasta flexibilitate este unul dintre aspectele care a trezit interesul specialistilor pentru limbajul Prolog.



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 2381
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved