|  | # Elemente de extensibilitate

"Obiectivul final si ideal al limbajelor extensibile este simplu si atractiv, constind din aceea ca se realizeaza un singur sistem universal de programare in care s-ar putea scrie software-ul oricarui calculator."
CHRISTENSEN

Dupa un exemplu de sistem extensibil, prezentam citeva considerente teoretice asupra extensibilitatii: preliminarii, notiuni de baza, definitia extendorului din punct de vedere matematic, o clasificare a extendorilor.

### Un exemplu de sistem extensibil

Intr-un anumit sens, toate programele de aplicatii implementate pe o anumita masina de calcul sint extensii ale sistemului de operare, pentru ca ele adauga noi functionalitati fara a ne forta sa-l recompilam. De exemplu, MS-DOS poate deschide si inchide fisiere text, dar nu stie cum sa le editeze, pentru aceasta trebuind rulata o aplicatie ( utilizata o extensie ) ca EDIT sau WordPerfect. Multe aplicatii mari, cum ar fi AutoCAD sau dBASE, sint extensibile, in sensul ca permit incarcarea unor extra-module care inzestreaza programele respective cu alte si alte noi capabilitati. Din nefericire, aceasta este o extensibilitate limitata si nu pretutindeni intilnita: nu putem anexa segmente din AutoCAD la dBASE sau viceversa. ( In ultima perioada au aparut sisteme software integrate care folosind tehnici precum OLE, DDE sau OpenDoc se apropie de acest deziderat. )

Putem insa extinde MS-DOS cu module pe care toate programele sa le utilizeze, incarcind ( via CONFIG.SYS ) la initializarea sistemului un nou driver pentru suportarea unui CD-ROM sau plotter, de pilda. De asemeni, avem libertatea de a instala programe rezidente ceea ce altereaza modul de administrare a memoriei.

Avem posibilitatea de a extinde MS-DOS prin rularea, peste el, a unui nou sistem de operare, diferit: Windows. Nu ne garanteaza nimeni insa siguranta si stabilitatea exploatarii, din cauza conflictelor Windows-ului cu celelalte programe rezidente care pot partaja intr-un mod neortodox resurse comune ca procesorul, fisierele, perifericele. Aceste probleme persista fiindca interfetele de exploatare a diferitelor aplicatii nu sint standardizate si sint modificate de fiecare generatie de programatori din intreaga lume, mai ales prin accesarea unor mecanisme nedocumentate. Foarte importanta este urmatoarea trasatura a acestui tip de extensibilitate "intr-un unic sens": codul nou adaugat poate utiliza rutine vechi, dar vechiul cod nu poate, in general, sa foloseasca noile module scrise, exceptind putinele cazuri cum ar fi cele referitoare la driverele de imprimanta .

Modulele nou introduse in sistem ( de pilda: nucleul unui procesor de texte ) vor trebui sa fie stabile, foarte bine testate si documentate pentru a putea fi utilizate cu succes de celelalte componente.

In prezent, fiecare aplicatie noua are incorporata propria procedura de editare de texte, de exemplu, cu propriile greseli strecurate in program. Concluzia: reinventarea de fiecare data a rotii, chiar mai proasta decit cea inventata prima data! Deci, avem nevoie de noi unelte de programare pentru a ne ajuta la conceperea cu eforturi minime a unor aplicatii mai bune, mai fiabile, standardizate.

Solutia este reprezentata de limbajele si sistemele extensibile!

### Considerente teoretice

#### Preliminarii

In lumea informaticii ne lovim mereu de barierele comunicarii om-masina si de gasirea unor mijloace adecvate scrierii in conditii ergonomice de aplicatii (aproape) impecabile. Astfel au fost create sute de limbaje de programare, aparind doua mari directii:

1. limbajele universale ( gindite a fi utilizate in multe domenii de activitate ) si
2. limbaje specializate ( apropiate cit mai mult de un anumit domeniu particular in care se doreste utilizarea calculatorului, in special de catre neinformaticieni ).

Dezavantajele primelor sint dimensiunile mari care fac improprii implementarile pe sisteme de calcul mai modeste, descrierea greoaie a unei anumite probleme, memorarea de catre programatori a unui numar impresionant de instructiuni si reguli. Dintre dezavantajele celorlalte, putem enumera acela ca nu se pot rezolva probleme din alte domenii de activitate si nici chiar din cele conexe.

Aceste neajunsuri pot fi inlaturate de limbajele extensibile care mostenesc insa toate avantajele limbajelor precedente ( usurinta in exploatare, versatilitate, apropiere de utilizatori, facilitati in implementarea pe calculatoare mici, existenta de biblioteci de programe complexe).

#### Notiuni de baza

Ideea este urmatoarea: sa se creeze o baza, numita baza extensibila, nucleul pentru toate dialectele (extinderile) ce vor deriva din ea prin adaugarea de noi elemente necesare fiecarui domeniu de activitate a utilizatorilor acestui limbaj extensibil. Asadar avem nevoie de un mecanism de extindere (sau de adaptabilitate), reprezentat prin extendori.
Extendorii sint mijloace de programare destinate definirii unor noi "unelte" software si utilizarii lor viitoare.

Extendorii ( in fapt elemente ale unui meta-limbaj peste limbajul de programare nucleu reprezentat prin baza ) pot fi de doua tipuri: de date si de actiuni: operatori, instructiuni, comenzi ( dirijari ). Extendorul este inclus printre elementele limbajului de baza si este reprezentat prin definirea unei extinderi ( ce va deveni ulterior element al limbajului de programare ) si prin apelul extinderii. Definirea si apelul se realizeaza in mod obisnuit prin intermediul unor meta-terminali ai limbajului.

In cazul extinderii indreptate spre hardware, tehnica de adaptabilitate se numeste reducere si se realizeaza cu ajutorul reductorului ( similar extendorului ).

In concluzie, un limbaj extensibil este compus din elemente de baza (incluzind extendorii) si din elemente derivate. Acestea ( adica extinderile ) vor "infasura" baza in mai multe nivele, fiecare element aflat pe nivelul i fiind definit prin intermediul nivelelor inferioare (incluzind nivelul bazei si cel putin un element al nivelului i-1 ) sau/si prin intermediul altor elemente de nivel i, in mod recursiv; uneori si prin intermediul elementelor de nivel mai inalt ( de exemplu: expresia matematica ).

Nivelele limbajului extensibil

Definitiile fiecarei extinderi, impreuna cu modulele care implementeaza efectiv aceste extinderi (secvente de cod, rutine de simulare), plus alte informatii vor forma asa-numita biblioteca extensibila.

Un limbaj de programare pentru a fi cu adevarat folositor trebuie implementat pe un calculator real. Avem asadar nevoie de un translator (compilator sau/si interpretor) extensibil in sarcina caruia revine definirea, fixarea ( introducerea ), identificarea, translatarea si utilizarea elementelor din care este compus un program sursa scris in limbajul extensibil pe care dorim sa-l utilizam. De mentionat ca extensibilitatea se poate manifesta atit in domeniul software, cit si in cel hardware.

Vom conveni sa numim realizare intregul proces de translatare a elementelor bazei si a celor extinse ( derivate ). Procesul de extindere se poate realiza:

- in sus ( se adauga noi elemente la limbajul extensibil, tinzindu-se atingerea limbajului natural formalizat )
- in jos ( extinderile sint indreptate spre hardware )
- pe orizontala ( elementele adaugate unui nivel sint definite recursiv, direct ori indirect, prin intermediul altor elemente situate pe acelasi nivel sau care vor fi create ulterior )

Ca tehnici de translatare a programelor putem enumera trei mari grupe:

- compilarea
- interpretarea
- compilarea-interpretarea

iar ca modalitati de translatare a elementelor extensibile exista translatarea:

- nivel-nivel
- nivel-direct
- nivel-nivel direct ( mixta )

Mai detaliat, translatarea nivel-nivel consta din traducerea fiecarui element aflat pe nivelul i prin intermediul unor elemente de pe nivelul i-1 si, iterativ, pina se ajunge la nivelul bazei.

Translatarea nivel direct trece direct elementele de pe nivelul i in baza.

Translatarea mixta combina cele descrise mai sus, unele elemente fiind transcrise direct in baza, altele prin intermediul elementelor de pe nivelul imediat inferior.

In ceea ce priveste compilarea, programul sursa va fi transformat in program ( cod ) obiect, scris in limbajul intern al unei masini virtuale/reale, deci la sfirsitul unui proces de compilare vom obtine ( in cel mai fericit caz ) un program executabil, de sine statator. Interpretarea, insa, presupune simularea fiecarei instructiuni de catre componentele interpretorului, pe baza datelor de intrare si a celor intermediare, furnizindu-se direct rezultatele calculului, fara a se genera cod obiect. Bine inteles si aici exista posibilitatea mixarii celor doua tehnici.

Tipurile de procesoare extensibile sint:

- preprocesorul
  realizarea extinderilor se infaptuieste inainte de realizarea elementelor bazei
- interprocesorul
  activitatile de realizare a elementelor de nivel si a elementelor de baza decurg simultan
- postprocesorul
  extinderile se realizeaza dupa realizarea elementelor din baza

Asadar, numarul total de procesoare extensibile care pot fi concepute este 27. Interdependentele dintre ele sint ilustrate de asa-numitul cub al extensibilitatii.

Cubul extensibilitatii

#### Extendorul

Fiind data T={ t1, ..., tn } multime de terminali ai gramaticii asociate unui limbaj de programare extensibil, impreuna cu multimea E a extendorilor limbajului si multimea EB a elementelor initiale, aceasta reuniune va forma baza limbajului EL0.

Limbajul adaptabil pe care dorim sa-l cream are o structura ierarhica:

ELi+1 include ELi, pentru orice i=0,1,...,n-1

unde ELi este multimea elementelor nivelului i, iar n=nivelul maxim creat.

Fiecare nivel i se obtine din precedentele, deci oricare element apartinind nivelului i se construieste cu ajutorul unor elemente de pe nivelele 0,1,...,i-1, participind cel putin un element al nivelului i-1.

Asadar, asociem fiecarui nivel o functie fi,j in care:

dom(fi,j)=produsul cartezian al multimilor T, EL0, ..., ELj-1, EL'j, EL'p, EL'g si
codom(fi,j)=ELk,
unde:

- j=1, 2, ..., n,
- i=1, 2, ..., Nj,
- Nj fiind numarul de elemente de pe nivelul j,
- EiLj=fi,j elementul i al nivelului j,
- ELj este multimea elementelor nivelului j,
- EL'k={ E1Lj, ..., EN'jLj } elementele nivelului k ce participa la definirea lui EiLj,
- cu N'j mai mic sau egal decit Nj,
- EL'p={ E1Lp, ..., ENpLp } elementele nivelului j ce participa la definirea lui EiLj ( prin recursie directa, folosindu-se elemente de pe acelasi nivel ),
- EL'g={ E1Lg, ..., ENgLg } elementele ce participa prin recursie indirecta la definirea elementului extensibil.

Crearea translatorului consta deci in elaborarea pentru fiecare functie fi,j a unui modul de translatare ti,j.

Insa orice limbaj de programare este compus din tipuri de date, operatii, instructiuni si dirijari ( control ). Din acest punct de vedere, un limbaj extensibil poate fi reprezentat astfel:

EPL={ D, O, I, Dir, R, E }

unde R si E sint reductorul, respectiv extendorul, iar Datele, Operatiile, Instructiunile si Dirijarile pot fi elemente de baza si elemente derivate.

Elementele bazei sint date axiomatic, cele de nivel superior sint definite prin intermediul elementelor nivelelor precedente, iar cele inferioare bazei se realizeaza cu ajutorul codului masina.

### Tipuri de extendori

- Extinderi simple

  - extindere tip-tip

    dintr-un element de tip dat se obtine un element de acelasi tip (data-data, operatie-operatie, instructiune-instructiune, control-control)

  - extindere cu tipuri diferite

    pornind de la un element de tip dat obtinem un nou element de tip diferit (data-instructiune, instructiune-operatie etc.)

- Extinderi compuse

  Un extendor poate fi ilustrat prin: E=(BPL,e,EPL), unde BPL semnifica limbajul de baza, EPL este limbajul extins, iar e functia de extindere. Exista patru tipuri de extinderi:

  1. extinderi compuse (m:n) E1=(BPL,e1,EPL)

     unde card(BPL)=m, card(EPL)=n

  2. extinderi compuse (m:1) E2=(BPL,e2,EPL)

     unde card(BPL)=m, card(EPL)=1

  3. extinderi compuse (1:1) E3=(BPL,e3,EPL)

     unde card(BPL)=1, card(EPL)=1

  4. extinderi compuse (1:n) E4=(BPL,e4,EPL)

     unde card(BPL)=1, card(EPL)=n

  Evident, tipul E3 este un tip de extendor simplu.

  Problema consta in a exprima extendorii de tip 1,2,4 respectiv prin intermediul extendorilor de tip 3.