Ada (limbaj de programare)
Ada limbaj de programare | |
---|---|
Autor |
|
Data de origine | 1980 |
Utilizare | scop general |
Paradigme | |
Tastare | |
Extensii comune | .adb .ads |
Influențată de | ALGOL 68 (Ada 83), Pascal (Ada 83), C ++ (Ada 95), Smalltalk (Ada 95), Java (Ada 2005) |
A influențat | C ++ , Eiffel , PL / SQL , VHDL , Ruby , Java , Seed7 |
Implementare referință | |
Site-ul web | www.adaic.org |
Ada este un limbaj de programare dezvoltat la sfârșitul anilor 1970 la inițiativa Departamentului Apărării al Statelor Unite (DOD). Atât specificațiile, cât și dezvoltarea limbajului au fost încredințate cererilor de oferte. Printre cele 17 propuneri trimise în urma licitației lansate de DOD, proiectul lui Jean Ichbiah , care la acea vreme lucra la CII Honeywell Bull , a fost ales în 1979 . Specificația a devenit un standard ANSI și ISO în 1983 , urmată de revizuiri ulterioare în 1995, 2005 și 2012. Un subset greu în timp real al limbajului este cunoscut sub numele de profilul Ravenscar . [1]
Ada combină principiile și tehnicile din diferite paradigme de programare , în special programarea modulară , programarea orientată pe obiecte , programarea concurentă și calculul distribuit . Deși interesul DOD a fost în principal în dezvoltarea aplicațiilor militare, Ada este un limbaj de uz general care se pretează să fie utilizat în orice domeniu de aplicație . Cu toate acestea, originea militară este dezvăluită în prezența caracteristicilor puternic orientate spre securitate ale codului; din acest motiv, limbajul este folosit și astăzi în multe contexte în care funcționarea corectă a software-ului este critică, cum ar fi astronautică , avionică , controlul traficului aerian , finanțe și dispozitive medicale. [2] [3] [4]
Compilatoarele Ada utilizate pentru dezvoltarea de software-uri critice pentru misiune trebuie să urmeze un proces de certificare conform standardului internațional ISO / IEC 18009 ( Ada: Conformity Assessment of a Language Processor ), implementat în Ada Conformity Assessment Test Suite (ACATS), parte integrantă la procesul de certificare desfășurat de laboratoare autorizate de Ada Compiler Assessment Authority (ACAA).
Numele inițial al limbajului trebuia să fie DOD-1 , dar mai târziu a fost schimbat în Ada în onoarea lui Ada Lovelace , un ilustru matematician de la începutul secolului al XIX-lea, creditat ca primul programator din istorie pentru dezvoltarea unui algoritm pentru calcularea numerelor de către Bernoulli pe motorul analitic al lui Charles Babbage .
Caracteristici
Ada moștenește câteva caracteristici stilistice fundamentale de la ALGOL , cu privire la care adaugă multe caracteristici de bază (cum ar fi sistemul de tipuri , înregistrări , indicatori sau enumerări , implementat în mare parte în stil Pascal ) și caracteristici avansate tipice limbajelor de programare moderne ( polimorfism , moștenire , excepții , sarcini ).
Limbajul oferă un număr mare atât de verificări statice (timp de compilare), cât și dinamice (timp de execuție ), care previn o mare varietate de erori (utilizarea incorectă a parametrilor, erori de tip, încălcarea intervalului și off-by-one) ). Comenzile dinamice pot fi dezactivate dacă doriți să maximizați eficiența, prin pragma Suppress
, [5] sau prin comutatoare specifice ale diferitelor compilatoare. Securitatea și fiabilitatea codului sunt de fapt unul dintre principalele aspecte care au ghidat dezvoltarea limbajului. [6]
"Salut Lume!" în Ada
O lume Hello în Ada este următoarea: [7]
cu Ada.Text_IO ; folosiți Ada.Text_IO ;
procedura Bună ziua este
începe
Put_Line ( "Bună ziua, lume!" );
sfârșit Bună ziua ;
Sintaxă
Spre deosebire de majoritatea limbajelor de programare, Ada nu distinge majuscule și minuscule . [8] Cele mai frecvente convenții stilistice implică scrierea cuvintelor cheie lingvistice în totalitate cu litere mici (sau, mai rar, în majuscule) și numele tuturor identificatorilor (tipuri, variabile, subrutine, pachete etc.) în cazuri de șarpe cu l inițială a fiecărui cuvânt capital. Comentariile sunt cu o singură linie, începând cu o liniuță dublă --
și se termină cu o întoarcere cu trăsura. Pentru identificatori și comentarii, Ada acceptă setul de caractere ISO 10646 , permițând astfel scrierea codului în caractere care nu sunt ASCII , iar lungimea maximă permisă pentru identificatori este legată de implementare (în implementările standard trebuie să fie egală cu cel puțin 200 de caractere) . [9]
Sintaxa Ada folosește câteva simboluri, preferând utilizarea cuvintelor în limba engleză. Simbolurile sunt atribuirea :=
, operatorii aritmetici elementari ( +
, -
, *
, /
și **
), operatorii de comparație ( <
, <=
, >
, >=
, =
, /=
), colonul :
să declare tipul unei variabile, săgeata =>
în agregate, virgula ,
ca separator în agregate, operatorul de acces la câmp .
, indicația intervalului ..
, bifați '
pentru a accesa atributele, caseta <>
pentru a indica un parametru variabil în declarații, punctul și virgula ;
pentru a separa parametrii unei rutine și pentru a termina afirmațiile. Instrucțiunea nulă constă din cuvântul cheie null
terminat de punct și virgulă, în timp ce o linie goală terminată de punct și virgulă nu este validă. Restul operatorilor sunt implementați prin cuvinte cheie ( and
, or
, rem
, mod
etc.).
Ada este un limbaj structurat , iar blocurile sunt delimitate de cuvinte cheie. Închiderea blocului conține o referință sau un identificator pentru a înțelege imediat căruia îi aparține deschiderea și pentru a evita confuzia, prevenind, de asemenea, potențialele legături sau alte erori similare. De exemplu, un subrutină care conține o buclă for
arată ca:
procedura Exemplul este
X : matrice ( domeniul întreg 1 .. 5 ) al întregului ;
începe
pentru I în bucla X ' Range
X ( I ) : = I ;
bucla de capăt ;
end Exemplu ;
Cuvinte rezervate
Limba, în raport cu standardul Ada 2012, are 73 de cuvinte rezervate : [10]
avorta
abs
abstract
Accept
acces
aliased
anexă
și
matrice
la
începe
corp
case
constant
declara
întârziere
delta
cifre
do
altceva
elsif
Sfârșit
intrare
excepție
Ieșire
pentru
funcţie
generic
mergi la
dacă
în
interfață
este
limitat
buclă
mod
nou
nu
nul
de
sau
alții
afară
primordial
pachet
pragma
privat
proceduri
protejat
a ridica
gamă
record
rem
redenumește
requeue
întoarcere
verso
Selectați
separa
niste
subtip
sincronizat
etichetat
sarcină
terminat
atunci
tip
pana cand
utilizare
cand
in timp ce
cu
xor
Există o omonimie între cuvintele rezervate access
, delta
, digits
, mod
și range
și atributele omonime, dar din moment ce atributele sunt întotdeauna precedate de un apostrof (numit tick ) nu există riscul de ambiguitate. [11]
Declarații variabile
Declarațiile variabile în Ada sunt făcute prin indicarea numelui entității declarate, urmat de :
și apoi de tip, acesta din urmă precedat de orice specificatori ( constant
, aliased
, not null
etc.). O sămânță statică sau dinamică poate fi opțional indicată după tip, separată prin :=
, iar declarația este finalizată prin ;
. Declarațiile pot fi plasate în caietul de declare
sarcini al unui pachet sau în partea declarativă a unei rutină sau bruiaj declare
. Mai multe variabile pot fi declarate în aceeași declarație, separând numele cu virgule, dar este doar zahăr sintactic și din punct de vedere tehnic declarațiile sunt încă distincte și independente una de cealaltă, astfel încât, de exemplu, o posibilă expresie de inițializare este evaluată o dată pentru fiecare variabilă. [12]
Este posibil să se definească variabile constante precedând tipul de cuvânt cheie constant
, caz în care este obligatoriu să se furnizeze o inițializare și este, de asemenea, posibil să se definească constante numerice prin omiterea tipului înainte de inițializare, care trebuie să conste dintr-o expresie statică , care este cunoscut pentru a compila timpul (tipul constantei este dedus din inițializatorul literal). Diferența dintre variabilele constante și constantele numerice este că primele sunt variabile calculate la runtime, în timp ce cele din urmă sunt rezolvate la compilare. [13]
- variabilă întreagă
N : întreg ;
- două variabile întregi, inițializate cu o valoare aleatorie
- (pot lua două valori diferite)
I , J : Număr întreg : = Aleatoriu ( semințe );
- variabilă constantă (evaluată la runtime)
F : Float constant : = Float ( I + J );
- constantă numerică (rezolvată static la momentul compilării)
π : constantă : = 3,14159_26535_89793_23846 ;
Mergi la
Spre deosebire de multe limbi moderne, Ada păstrează declarația goto
. Deși, în general, este depreciat în programarea structurată , este de fapt o instrucțiune utilă pentru generarea automată de cod pornind de la surse în alte limbi sau specificații formalizate la nivel înalt. Este, de asemenea, acceptabil în anumite contexte, cum ar fi sărind spre sfârșitul unui bloc [14] (de exemplu, o iterație a unei bucle) sau ieșirea din bucle adânc imbricate, [15] unde este mai ușor de citit decât continue
similare break
sau continue
în alte limbi ca punctul final al saltului în cod este clar indicat de etichetă (în timp ce break
în limbi precum C poate fi predispusă la erori ). [16]
procedura Print_Integers este
începe
pentru I în 1 .. 20 de bucle
Pune (Integer 'Image (I));
dacă am mod 5 = 0 atunci
New_Line ;
du-te Continuă ; - mergi la
incheie daca ;
Put ( "," );
<<Continue>> - etichetă
bucla de capăt ;
end Print_Inters ;
Tip sistem
Ada este un limbaj puternic tastat și sigur . [17] Spre deosebire de C și derivatele sale, Ada nu permite conversii de tip implicite (cu excepția tipurilor universale și a tipurilor de acces anonime) [18], iar conversia de tip se face scriind numele tipului urmat de variabilă pentru a converti între paranteze [19] , de exemplu:
Conversia este procedură
X : Float : = 2,9 ;
Y : întreg ;
începe
Y : = X ; - ilegal (atribuiți valoarea Float variabilei Întreg)
X : = X + 1 ; - ilegal (operatorul + nu este definit pentru tipurile mixte)
X : = X + 1,0 ; - legal
Y : = Întreg ( X ); - conversie tip (cu rotunjire): acum Y este 3
încheie conversia ;
Tipul unui literal poate fi indicat în mod explicit cu o sintaxă similară cu conversia adăugând o bifă înainte de paranteze de deschidere. Acest lucru este util mai ales în caz de ambiguitate, atunci când același literal (cum ar fi un șir sau o valoare enumerativă) se poate referi la diferite tipuri. [20]
Tipuri predefinite
Spre deosebire de C și derivatele sale, nu există cuvinte cheie în Ada care să identifice tipurile primitive, iar toate tipurile predefinite sunt definite în biblioteca standard. Tipurile de bază predefinite (cum ar fi Integer
, Float
sau Character
) sunt definite în pachetul Standard
, dar pentru a maximiza portabilitatea, se consideră o bună practică să nu utilizați direct tipurile predefinite și să le definiți în schimb, chiar și pentru cele mai simple tipuri numerice. [21]
Tipurile definite în pachetul Standard
sunt întotdeauna vizibile în fiecare parte a programului, în timp ce celelalte tipuri definite în pachetele rămase ale bibliotecii standard necesită o clauză with
pentru a fi vizibile. Tipurile definite în Standard
sunt: [22]
-
Integer
: tip discretInteger
, care ia valori într-un interval de extensie legat de implementare, nu mai puțin de .. .-
Natural
: subtip deInteger
care poate presupune doar valori non-negative; -
Positive
: subtip care poate presupune doar valori pozitive nenule;
-
-
Float
: tip cu virgulă mobilă cu cel puțin șase cifre; -
Duration
: tip punct fix, folosit pentru a exprima un timp în secunde; -
Character
,Wide_Character
,Wide_Wide_Character
: tipuri speciale de enumerare, utilizate pentru caractere text codate pe 8, 16 și respectiv 32 de biți (ultimele două au fost adăugate în Ada 95 și respectiv Ada 2005) -
String
,Wide_String
,Wide_Wide_String
: șiruri de lungime fixă, constând din tablouri de caractere. Alte două varietăți de șiruri, mai flexibile, dar și mai grele din punct de vedere al calculului, sunt definite în alte pachete ale bibliotecii și suntAda.Strings.Bounded.Bounded_String
(pentru șiruri cu lungime variabilă până la o valoare maximă) șiAda.Strings.Unbounded.Unbounded_String
(pentru șiruri fără restricții de lungime variabilă), ale căror pachete respective oferă și rutine de manipulare; -
Boolean
: tip enumerativ care poate asuma valorileFalse
șiTrue
și care are o anumită semantică.
Pachetele System
și System.Storage_Elements
oferă câteva tipuri care sunt utile pentru programarea la nivel scăzut: [23]
-
System.Address
: reprezintă o adresă de memorie; -
System.Storage_Elements.Storage_Offset
: reprezintă un offset de memorie, care poate fi adăugat sau scăzut dintr-o adresă pentru a obține o altă adresă; -
System.Storage_Elements.Storage_Count
: un subtipStorage_Offset
care poate lua doar valori non-negative, folosit pentru a reprezenta dimensiunea unei structuri de date; -
System.Storage_Elements.Storage_Element
: reprezintă unitatea minimă de memorie adresabilă (adică un singur octet în majoritatea implementărilor); -
System.Storage_Elements.Storage_Array
: matrice deStorage_Element
.
Declarație de tipuri și subtipuri
Tipurile pot fi definite utilizând type
cuvântului cheie, sub forma unei enumerări, ca tip cu virgulă mobilă cu cuvântul cheie cu digits
sau pornind de la un alt tip preexistent, utilizând cuvântul cheie new
, în timp ce atributul 'Base
unui tip oferă tipul de bază din care derivă. Pornind de la un tip este posibil să se definească un subtip (cu subtype
cuvântului cheie), care constă dintr-un set de valori conținute în domeniul tipului din care derivă. [24]
- nou tip numeric definit pornind de la Integer
tipul Ziua este nou întreg ;
- subtipul zilei
subtipul Day_Of_Month este intervalul Day 1 .. 31 ;
Tipuri enumerative
Tipurile enumerative pot fi specificate prin indicarea valorilor posibile între paranteze. Literalele de tip enumerativ pot intra în conflict și, în acest caz, tipul este specificat în mod explicit pentru a rezolva ambiguitatea. Este posibil să se specifice o serie de valori enumerative și este posibil să se declare subtipuri enumerative care iau doar o parte din valorile tipului din care derivă.
Operatorii de comparație sunt definiți automat pentru tipurile enumerative (ordinea este dată de poziția din declarație, începând de la valoarea minimă spre maximă) și au mai multe atribute utile, printre care 'First
și 'Last
, care returnează primul și ultima valoare de tip, 'Succ
și 'Pred
, care returnează valorile anterioare și următoare, 'Pos
și 'Val
, care returnează indicele pozițional (bazat pe zero) al valorii (adică poziția din declarație) respectiv și valoarea asociată unui index. [25]
procedurile P este
tipul Divinitatea este ( Jupiter , Juno , Minerva , Eros , Venus );
tip Planeta este ( Mercur , Venus , Pământ , Marte , Jupiter , Saturn , Uranus , Neptun );
subtipul Rocky_Planet este gama Planet Mercur .. Marte ;
P1 : Planeta : = Mercur ;
D1 : Divinitate : = Juno ;
- literali ambigui
P2 : Planeta : = Planeta ( Jupiter );
D2 : Divinitate : = Divinitate '( Jupiter );
B : Boolean ;
I : Întreg ;
D : Divinitate ;
P : Planeta ;
începe
- exemple de operatori și atribute
B : = Juno < Minerva ; - Adevărat
I: = Planeta 'Pos (Venus); - 1
P : = Rocky_Planet ' Last ; - Marte
D : = Divinity ' Pred ( Minerva ); - Juno
capătul P ;
Matrice
Matricile sunt definite utilizând array
cuvinte cheie, specificând între paranteze natura indicilor (care pot fi de orice tip discret). În plus față de tip, este posibilă specificarea unui interval pentru indicii matricei, indicând nu dimensiunea structurii, ci o pereche de valori minime și maxime pentru index, eliminând la rădăcină problema alegerii între zero și unul. Elementele unui tablou sunt accesate prin marcarea indexului între paranteze rotunde. [26]
Un tip de matrice poate fi definit anonim în declarația variabilei sau un tip specific de matrice poate fi declarat cu cuvântul cheie type
. Diferența fundamentală este că, în primul caz, două matrice nu pot fi atribuite reciproc, chiar dacă sunt declarate cu un tip anonim care arată la fel, deoarece sunt formal două tipuri diferite (chiar dacă declarația are loc în aceeași linie prin separarea numele variabilelor cu virgulă, deoarece această notație este doar zahăr sintactic pentru două declarații distincte). [27]
Tablourile acceptă tranșarea, atribuind simultan o gamă (nu neapărat statică) de indici, chiar și cu elemente suprapuse. [28]
procedurile P este
- matrice de tip anonim
A , B : matrice ( domeniul întreg 1 .. 5 ) de Float ;
- tip pentru matrice, cu lungime variabilă
tip Vector este matrice ( interval întreg <>) de Float ;
- subtip pentru matrice de lungime fixă
subtipul Vector_5 este Vector ( 1 .. 5 );
- matrice cu index 1..5
C , D : Vector_5 ;
- matrice cu index 1..6
E : Vector ( 1 .. 6 );
începe
A : = B ; - ilegală (nu compilează), cele două variabile au tipuri diferite (anonime)
C : = D ; - legal
C : = E ; - ilegal
A ( 1 .. 3 ) : = B ( 2 .. 4 ); - felie
A ( 1 .. 3 ) : = A ( 2 .. 4 ); - felie cu element suprapus (ok)
capătul P ;
Este posibil să se declare matrice multidimensionale native, separând indexurile cu virgule, sau sub forma unei matrice de matrice (și, prin urmare, matrice zimțate ), în acest caz având grijă să acordăm atenție ordinii declarațiilor. [29]
procedurile P este
A : matrice ( interval întreg 1 .. 5 , interval întreg 2 .. 7 ) de Float ; - matrice de dimensiunea 2
B : matrice ( interval întreg 2 .. 7 ) de matrice ( interval întreg 1 .. 5 ) de float ; - matrice de matrice
începe
A ( 1 , 2 ) : = 5,0 ; - acces la un element dintr-o matrice multidimensională
B ( 1 ) ( 2 ) : = 5,0 ; - acces la un element dintr-o serie de matrice
capătul P ;
Pentru tablouri, puteți utiliza literale (numite agregate) în declarații sau instrucțiuni, constând dintr-un set de valori între paranteze, separate prin virgule. Agregatele pot fi poziționale sau nominative: în primul caz, corespondența valorii cu indicele la care se referă este dată de poziția din agregat (ordinea valorilor trebuie să urmeze deci cea a elementelor matricei ), în al doilea caz în loc pentru fiecare valoare, specificați indexul, folosind simbolul =>
pentru a-l separa de valoare. Este posibil să atribuiți aceeași valoare mai multor indici, utilizând intervalul ..
dacă acestea sunt consecutive sau sunt o conductă |
pentru a enumera valori non-consecutive. Sintaxa agregatelor este strictă și nu permite inițializări parțiale, dar este posibilă specificarea individuală a unor elemente și completarea atribuirii cu o valoare pentru toate elementele rămase, utilizând cuvântul cheie others
. [30]
- agregat pozițional
A : matrice ( domeniul întreg 1 .. 5 ) a întregului : = ( 1 , 2 , 3 , 4 , 5 );
- agregat nominativ, cu interval și altele (agregatele pentru matricile imbricate sunt poziționale)
B : matrice ( interval întreg 2 .. 7 ) de matrice ( interval întreg 1 .. 5 ) de număr întreg
: = ( 2 .. 4 | 6 => ( 1 , 3 , 5 , 7 , 9 ), altele => ( 2 , 4 , 6 , 8 , 10 ));
Puteți aplica operatorii not
, and
, or
și xor
la matrici unidimensionale de valori Boolean
de același tip și lungime, iar rezultatul este un tablou ale cărui componente sunt calculate prin aplicarea operatorului la perechile de componente individuale ale operanzii matrice. [31]
Record
Înregistrările pot fi definite cu cuvântul cheie record
, specificând câmpurile în același mod ca și declarațiile variabile (inclusiv posibilitatea de a atribui valori implicite). Este posibil să accesați câmpurile unei înregistrări cu notație punct și să utilizați agregate construite similar cu cele ale matricelor. De asemenea, puteți defini o înregistrare fără câmpuri cu perechea de cuvinte cheie cu null record
, care este utilă pentru definirea tipurilor abstracte sau pentru extinderea unui tip fără a adăuga câmpuri noi. [32]
procedurile P este
- record
tip Date este
record
Ziua : intervalul întreg 1 .. 31 : = 1 ;
Lună : Nume_Lună : = ianuarie ; - Name_Month este un tip de enumerare
An : întreg : = 1970 ;
înregistrare finală ;
D , E : Data ;
tipul Null_Record este înregistrare nulă ; - înregistrări fără câmpuri
începe
D: = (10 ianuarie 1995);
Și. Ziua: = D. Ziua ;
capătul P ;
Tipuri parametrice
Puteți utiliza parametri (numiți discriminanți) în declarația unui tip, care va fi specificat atunci când se declară variabile sau se derivă un tip non-parametric. [33]
pachet Discriminanți este
- tastați pentru un text de lungime generică, specificat de dimensiunea discriminantă
tip Text ( Dimensiune : Pozitiv ) este
record
Poziție : pozitivă : = 1 ;
Date : Șir ( 1 .. Dimensiune );
înregistrare finală ;
- variabilă pentru un text de 100 de caractere
T : Text ( 100 );
sfârșitul Discriminant ;
Tipuri limitate
Un alt mecanism de control al tipului este dat de posibilitatea de a defini tipuri limitate, utilizând cuvântul cheie limited
. Tipurile restricționate au doar operațiunile declarate în pachet, deci nu pot fi atribuite cu :=
și nu au operațiile de comparație implicite =
și /=
. Un tip privat poate fi definit ca limitat, dar implementat intern ca nelimitat, în acest caz tipul este limitat în afara pachetului, dar nu este limitat în partea privată a acestuia, asigurând flexibilitate în cadrul pachetului, acolo unde operațiunile predefinite rămân disponibile și în același timp, controlul asupra tipului față de cei care îl utilizează în afara ambalajului. [34]
Modularitate
Ada este un limbaj structurat și vă permite să împărțiți codul în mai multe unități de compilare (rutine și pachete), care pot fi compilate separat.
Rutină
Ada acceptă două tipuri de rutine , funcții și proceduri, declarate cu cuvintele cheie function
și procedure
. [35] Primele au o valoare de returnare și pot fi utilizate numai în contextul unei expresii (în Ada, spre deosebire de limbile derivate din C, nu există declarații de expresie ), în timp ce acestea din urmă nu au valoare de returnare și pot fi folosite numai pentru instrucțiuni. Ambele proceduri și funcții constau din două părți distincte, o parte declarativă între cuvintele cheie is
și begin
, care poate conține doar declarații (cum ar fi variabile, tipuri sau alte rutine imbricate) și o parte care conține doar instrucțiuni, între cuvintele cheie begin
și end
. Este posibil să inserați declarații în afara părții declarative folosind un bloc declare
, iar declarațiile aferente sunt vizibile numai în interiorul acesteia. O rutină poate fi o unitate de compilare autonomă sau poate fi declarată și implementată într-un pachet sau în partea declarativă a unei alte rutine.
Parametrii unei rutine sunt specificați între paranteze rotunde, iar Ada acceptă trecerea parametrilor atât prin valoare, cât și prin referință, în trei moduri diferite: in
, out
și in out
. Parametrii au trecut în modul in
pot fi citite numai de rutină, cei din modul de out
poate fi scris numai, cei în modul in out
poate fi citit și scris. Modul unui parametru este specificat după i :
și înainte de tip și, dacă este omis, se presupune in
este implicit. Este posibil să se definească o valoare implicită pentru parametri, care în acest fel devin opționale și pot fi omise în apelurile la procedură: în acest caz se utilizează valoarea implicită. Pentru parametrii și valorile returnate ale tipului de acces este posibilă specificarea excluderii nule, ceea ce determină o excepție de execuție dacă parametrul (sau valoarea returnată) sunt null
. Rutinele sunt invocate urmărindu-și numele cu o pereche de paranteze rotunde care conțin parametrii, dar dacă o rutină este declarată sau apelată fără a trece niciun parametru, parantezele rotunde pot fi omise. Rutinele definite pe tipurile etichetate pot fi, de asemenea, apelate cu notare punct în raport cu parametrul tip etichetat. [36]
- exemplu de procedură cu parametru opțional
procedura Increment ( X : In out Integer ; Increment : Integer : = 1 ) este
începe
X : = X + Increment ;
sfârșit Increment ;
- exemplu de apel într-o altă bucată de cod
procedurile P este
N : întreg : = 0 ;
începe
Increment ( N );
- acum N este 1
Creșterea ( N , 3 );
- acum N este 4
capătul P ;
Operatorii sunt, de asemenea, funcții, definite prin indicarea numelui operatorului între ghilimele duble, iar Ada acceptă supraîncărcarea acestora, precum și rutina de suprasarcină și suprascriere în general. [37]
- exemplu de suprasarcină a operatorului + cu operanzi de tip T
- a cărei sumă este definită în funcția Sum_T
funcția "+" ( Stânga , Dreapta : T ) returnează T este
începe
returnează Suma_T ( Stânga , Dreapta );
sfârșitul „+” ;
Operatorii sunt identificați prin următoarele cuvinte cheie: [38]
abs și mod not or rem xor
= / = << = >> =
+ - * / ** &
Pachet
Modularitatea codului la un nivel mai abstract decât rutinele se realizează prin intermediul pachetelor. Un pachet este împărțit în două părți distincte, specificație și implementare, iar unele compilatoare (cum ar fi GNAT ) necesită să introduceți o singură unitate de compilare pe fișier, împărțind de asemenea specificațiile și implementarea în două fișiere separate (respectiv .ads
și .adb
). Specificația reprezintă interfața pachetului accesibilă extern și poate fi compilată independent de implementare, facilitând testarea timpurie. Implementarea conține codul propriu-zis al rutinelor definite în interfață, plus orice alte rutine neaccesibile din afara pachetului. Pachetele pot fi compilate separat și, dacă o implementare a pachetului se modifică fără a-și modifica specificațiile, orice alte pachete dependente de acesta nu trebuie recompilate. [39]
Declarațiile rutinelor conținute trebuie inserate în specificația pachetului (fișierul .ads
), în timp ce implementarea este plasată în corp (fișierul .adb
). Specificația și implementarea trebuie să aibă o conformitate completă a tipului , adică numele rutinei, orice tip de returnare, număr, tip, mod, ordine, valoare implicită și numele parametrilor trebuie să fie identice în specificație și în implementare, cu excepția cazului în care unele diferențe nesubstanțiale: un literal numeric poate fi înlocuit cu un diferit formal, dar cu aceeași valoare, un identificator poate fi adăugat ca prefix în notația punct , o indicație explicită a modului in
poate fi omis, un set de parametri ai același subtip poate fi indicat separat. Toate rutinele declarate în caietul de sarcini trebuie neapărat să fie implementate în corp, cu câteva excepții: proceduri nule (a căror declarație se termină cu is null
și este echivalentă cu o procedură care conține doar o declarație nulă), rutine abstracte (care nu au nicio implementare ) și funcții constând dintr-o expresie condițională (care este inserată direct în caietul de sarcini). [40]
- specific
pachetul P este
- rutine implementate în organism
Proceduri de sumă ( A , B : în întreg ; S : în întreg );
funcția Sum ( A , B : Întreg : = 0 ) returnează Întreg ;
- rutine neimplementate în organism
procedura Foo ( A : Integer ) este nulă ; - procedura nulă
funcția Baz este abstractă ; - rutină abstractă
function Bar ( A : Integer ) return Boolean is - functie constand dintr-o expresie conditionala
( dacă A > 0 atunci adevărat altceva fals );
capătul P ;
- implementare
corpul pachetului P este
procedura Suma ( A , B : în întreg ; S : în întreg ) este
începe
- începutul instrucțiunilor
S : = A + B ;
sfarsit Suma ;
funcție Sum ( A , B : Întreg : = 0 ) return Întreg este
- începutul părții declarative
C : întreg ;
începe
- începutul instrucțiunilor
C : = A + B ;
retur C ;
sfarsit Suma ;
capătul P ;
Puteți crea o ierarhie de pachete în două moduri: cu cuibărirea, definirea unui pachet în altul și cu rudenia, definirea unui pachet ca fiind un copil al celuilalt (separarea părintelui și a copilului cu notare punct ). Pachetele pentru copii pot fi, de asemenea, definite ca private și, prin urmare, sunt total inaccesibile în afara pachetului părinte. [41]
- pachet părinte
pachet Tatăl este
- pachet imbricat
pachetul Îmbricat este
...
end Cuibărit ;
sfârșește Tată ;
- pachet pentru copii
pachet Tată.Fiu este
...
end Padre.Figlio ;
-- package figlio privato
private package Padre.Figlio_Privato is
...
end Padre.Figlio_Privato ;
Tali tipi avranno perciò una vista parziale nella parte pubblica, e una vista completa nella parte privata del package. I package figli condividono la parte privata del padre ma non dei fratelli, tuttavia è possibile importare un package fratello in modo da poterne vedere anche la parte privata usando la clausola private with
invece della solita with
. [42]
package P is
type T is private ; -- T è visibile fuori da P, ma non la sua implementazione
private
-- S non può essere visto né usato fuori dal package P
type S is
record
...
end record ;
-- completa la definizione di T
type T is
record
-- i campi di T non sono visibili né utilizzabili fuori dal package P
I : Integer ;
end record ;
end P ;
Generics
In Ada le routine oi package possono avere dei parametri risolti staticamente a tempo di compilazione, specificati facendo precedere l'unità dalla keyword generic
e specificati tra parentesi tonde quando si istanzia l'unità generica. I generics sono un meccanismo statico che consente un riuso del codice, permettendo di istanziare la stessa unità con parametri di tipo differenti, ma a differenza di altri linguaggi i parametri generici possono essere non solo tipi, ma anche valori o routine. Nel caso di package generici, non può essere usata su essi la clausola use
(può essere usata solo sulle loro istanze concrete) ed ogni eventuale loro package figlio deve necessariamente essere generico. [43]
Ad esempio, una procedura per scambiare due elementi può essere parametrizzata rispetto al tipo degli stessi
generic
type T is private ;
procedure Scambia ( A , B : in out T );
procedure Scambia ( A , B : in out T ) is
Temp : T ;
begin
Temp := A ;
A := B ;
B := Temp ;
end Scambia ;
ed essere istanziata per l'uso su tipi diversi: [44]
procedure Scambia_Interi is new Scambia ( Integer );
procedure Scambia_Float is new Scambia ( Float );
Analogamente un package può implementare uno stack generico
generic
type T is private ;
Capacità : Positive ;
package Stack is
procedure Push ( X : T );
function Pop return T ;
private
A : array ( 1 .. Capacità ) of T ;
Posizione : Integer range 0 .. Capacità ;
end Stack ;
che può essere istanziato per contenere oggetti di differente tipo e scegliendo di volta in volta la capacità massima: [45]
package Int_Stack is new Stack ( Integer , 100 ); -- stack con una capacità di 100 valori interi
package Float_Stack is new Stack ( Float , 50 ); -- stack con una capacità di 50 valori float
Parametri di tipo
Nel caso più semplice, un parametro di tipo generico è istanziabile e ha solo la definizione di assegnamento e uguaglianza. Possono essere specificati diversi attributi del parametro di tipo, che ne modificano l'interfaccia: può essere limitato, può avere dei discriminanti (anche non specificati, indicati con il box <>
, in tal caso il tipo non è istanziabile), può essere tagged, astratto, può essere discendente di un tipo preesistente o può essere un'interfaccia con una o più interfacce progenitrici. Alcuni esempi di parametri di tipo generici: [46]
generic
type A is private ; -- tipo privato
type B is limited ; -- tipo limitato
type C ( X : Integer ); -- tipo con discriminante X
type D (<>); -- tipo con discriminante sconosciuto
type E is tagged ; -- tipo tagged
type F is new T ; -- tipo derivato dal tipo non tagged T
type G is new T with private ; -- tipo derivato dal tipo tagged T
type H is interface and I and J ; -- tipo interfaccia con due progenitrici
package Generic_Package is
...
end Generic_Package ;
Per i tipi enumerativi e numerici esistono anche delle indicazioni particolari, e per ognuno di essi sono disponibili le operazioni predefinite per tale tipo. [47]
generic
type A is (<>); -- tipo enumerativo
type B is range <>; -- tipo numerico con segno
type C is mod <>; -- tipo numerico modulare
type D is digits <>; -- tipo in virgola mobile
type E is delta <>; -- tipo in virgola fissa
type F is delta <> digits <>; -- tipo decimale
Parametri routine
Poiché per un tipo generico si assume l'esistenza delle sole funzioni predefinite per quella categoria di tipi, può essere necessario passare come parametro anche una o più routine. Ad esempio, implementando un albero binario di ricerca che possa contenere chiavi di un tipo qualsiasi, per effettuare le operazioni di inserimento o ricerca è necessario poter comparare le chiavi, ma l'operatore di confronto <
non è predefinito per ogni tipo. Si può quindi ovviare al problema passando tale operatore come parametro generico. I parametri generici per le routine devono essere quindi passati esplicitamente quando si istanzia il package, ma possono essere omessi se nella dichiarazione del parametro generico si specifica is <>
. In questo caso la routine viene scelta automaticamente quando si istanzia il package, a patto che sia definita e visibile, sia unica e abbia completa type conformance con la dichiarazione del parametro generico. [48]
-- package generico
generic
type T is private ;
with function "<" ( Sinistra , Destra : T ) return Boolean is <>;
package Albero_Binario is
...
end Albero_Binario ;
-- package che usa l'Albero_Binario
package P is
type Data is
record
...
end record ;
function Confronta_Data ( Sinistra , Destra : Data ) return Boolean ;
-- istanzia il package generico sul tipo Data
package Albero_Data is new Albero_Binario ( Data , Confronta_Data );
-- l'operatore può anche essere omesso, perché esiste ed è visibile per il tipo Float
package Albero_Float is new Albero_Binario ( Float );
end P ;
Memoria dinamica
La memoria dinamica (chiamata storage pool ) è gestita ad alto livello ed è typesafe . Il linguaggio non fornisce puntatori flessibili come quelli del C (che sono una tra le principali fonti di bug, errori e vulnerabilità), ma utilizza dei riferimenti (detti access type ) che conservano informazioni sull'accessibilità degli oggetti ai quali fanno riferimento e seguono precise regole di accessibilità, prevenendo il problema dei dangling pointer . La versatilità del linguaggio per applicazioni a basso livello è comunque garantita, grazie all'attributo 'Address
e al package System
, che permettono di manipolare indirizzi di memoria raw. L'interfaccia Interfaces.C.Pointers
fornisce inoltre dei puntatori in stile C, utili quando si interfaccia un'applicazione Ada con una in C.
La semantica del linguaggio permette la garbage collection , la cui presenza è però legata all'implementazione: solitamente è assente nei compilatori per le architetture native (in quanto può influire in maniera imprevedibile sul timing, e questo è un effetto deleterio nei sistemi real-time ) [49] ma è talvolta presente per i compilatori che hanno come architettura target la JVM . La deallocazione può essere effettuata manualmente, istanziando l'unità generica Ada.Unchecked_Deallocation
, che deve essere usata con attenzione per evitare di deallocare oggetti nello stack o creare dangling pointer. [50] Per aumentare la sicurezza si può applicare un pattern di smart pointer , creando oggetti che contano e gestiscono autonomamente i riferimenti alle risorse, in modo che il programmatore del client non debba deallocare niente in maniera esplicita. [51]
Programmazione orientata agli oggetti
A differenza di molti linguaggiorientati agli oggetti , Ada non ha un costrutto per le classi analogo a C++ o Java. Tra i principali aspetti della programmazione OOP vi sono la possibilità di distinguere il tipo di un oggetto a runtime, di definire un tipo a partire da un altro e di permettere a tali tipi di ereditare le operazioni primitive del tipo da cui deriva. [52] In Ada la differenza tra variabili che sono "oggetti" e che non lo sono consiste nel fatto che le prime conservano a runtime le informazioni sul proprio tipo, consentendo il polimorfismo e il dynamic dispatch .
Ereditarietà
L' ereditarietà si ha tramite estensione, che rende possibile aggiungere nuovi campi, mantenendo anche quelli ereditati. È possibile convertire un oggetto (record tagged) di un sottotipo in un tipo antenato, mentre non è possibile fare il contrario, ma è possibile assegnare un oggetto di tipo antenato ad un tipo discendente usando un aggregato che completi i campi mancanti ( extension aggregate ). L'estensione S
di un tipo tagged T
tramite la keyword new
eredita anche le operazioni primitive per T
, ovvero quelle subroutine dichiarate nello stesso package in cui è dichiarato T
e che abbiano un parametro o un risultato di tipo T
. [53] I tipi derivati hanno quindi un'interfaccia che è sempre un sovrainsieme di quella del tipo da cui derivano, e l'implementazione effettiva delle operazioni ereditate può essere modificata tramite override (l'indicazione esplicita di override nella dichiarazione dell'operazione tramite la keyword overriding
, o viceversa di non override con not overriding
, è facoltativa ma costituisce un utile controllo statico a tempo di compilazione). [54] Le funzioni di un tipo tagged possono essere richiamate con la dot notation sulla variabile dell'oggetto. L'incapsulamento dello stato interno degli oggetti non è diverso da quello per i tipi non tagged, ed è ottenuto usando il meccanismo di incapsulamento dei package . L'estensione di un tipo può avvenire anche privatamente, per cui i campi aggiunti nell'estensione non sono visibili all'esterno del package. [55]
package Persone is
type Persona is tagged -- tipo tagged
record
Nome : String ;
Cognome : String ;
Età : Natural ;
end record ;
function Salario ( P : Persona ) return Float ; -- operazione primitiva, restituisce zero come default
type Lavoratore is new Persona with -- tipo derivato aggiungendo nuovi campi
record
Mansione : Job ; -- un qualche tipo enumerativo
Anzianità : Natural ;
end record ;
overriding
function Salario ( L : Lavoratore ) return Float ; -- override di un'operazione primitiva
type Studente is new Persona with
record
Istituto : School ; -- tipo enumerativo
Corso : Year ; -- altro tipo enumerativo
end record ;
-- Studente eredita la funzione Salario di Persona, che restituisce zero
-- estensione privata
type Dottorando is new Studente with private ;
-- dichiarazione di un oggetto Studente
S : Studente := ( "John" , "Doe" , 20 , "Trinity College" , III );
-- conversione da un sottotipo ad un tipo antenato
P : Persona := Persona ( S );
-- assegnamento ad un sottotipo con un extension aggregate
T : Studente := ( P with Istituto => "MIT" , Corso => IV );
private
type Dottorando is new Studente with
record
-- i campi aggiunti non sono visibili fuori dal package
Dipartimento : Department ;
end record ;
end Persone ;
Dynamic dispatch
Con il termine "classe" in Ada si indica un insieme di tipi ( class wide ), costituito da un tipo tagged e da tutti i tipi da esso derivati direttamente o indirettamente. È possibile definire operazioni che hanno parametri o risultato di un tipo class wide usando l'attributo 'Class
, ad esempio per un tipo T
il suo tipo class wide viene indicato con T'Class
. La differenza tra un'operazione con un parametro di tipo T
e uno di tipo T'Class
è che nel primo caso la scelta della routine da eseguire è determinata staticamente a tempo di compilazione, nel secondo caso è determinata dinamicamente a runtime (dynamic dispatch). [56] Se nell'esempio precedente si aggiunge al tipo Persona
la seguente operazione primitiva
function Reddito_Annuo ( P : Persona ) return Float is
return 12.0 * P . Salario ;
end Reddito_Annuo ;
si ha che la funzione restituirà sempre zero per tutti gli oggetti, anche dei tipi come Lavoratore
che avessero salario non nullo, perché al suo interno viene sempre richiamata staticamente la funzione Salario
definita per il tipo Persona
, che restituisce zero. Se invece l'operazione è definita come
function Reddito_Annuo ( P : Persona ' Class ) return Float is
return 12.0 * P . Salario ;
end Reddito_Annuo ;
il dispatch della funzione Salario
avviene dinamicamente e il risultato restituito è quello corretto anche per gli oggetti di tipo Lavoratore
. [57]
Tipi astratti e interfacce
Se un tipo tagged viene dichiarato astratto, tramite la keyword abstract
, non è possibile dichiarare variabili di quel tipo, ma solo usarlo come base da cui derivare altri tipi. I tipi astratti possono avere componenti e routine concrete, ma anche routine a loro volta definite come astratte, che non sono provviste di implementazione. Quando si deriva un tipo concreto da un tipo astratto, tutte le sue routine astratte devono necessariamente essere oggetto di override. Un'interfaccia è un tipo dichiarato con la keyword interface
, ed è analogo ad un tipo astratto ma ha maggiori restrizioni, in quanto non può avere componenti né routine concrete, salvo procedure nulle o routine con parametri class wide .
Ada ha un meccanismo di ereditarietà singola per le implementazioni e multipla per le interfacce, simile al Java, per cui è possibile definire tipi che estendono al massimo un tipo concreto o astratto, ma allo stesso tempo possono implementare un numero arbitrario di interfacce. Questo previene possibili conflitti o ambiguità derivanti dall'ereditarietà multipla completa, ma conserva comunque la flessibilità consentendo ad un tipo di poter avere più interfacce di routine. [58] Le interfacce possono essere usate anche con estensioni private, ma in quel caso la vista completa e quella parziale del tipo devono essere conformi rispetto alle interfacce implementate, per cui non è possibile aggiungere o togliere interfacce nel completamento privato della dichiarazione. [59]
package P is
-- tipo astratto: può avere campi, procedure concrete e astratte
type S is abstract tagged
record
...
end record ;
procedure Foo ( X : S );
procedure Baz ( X : S ) is abstract ;
-- interfaccia: non può avere campi né operazioni concrete (che non
-- siano nulle o con parametro class wide)
type T is interface ;
procedure Foo ( X : T ) is abstract ;
procedure Baz ( X : T ) is null ;
procedure Bar ( X : T ' Class );
end P ;
Tipi controllati
In Ada non esiste il concetto di costruttore , ma è possibile sostituirne le caratteristiche funzionali usando un tipo controllato. Un tipo controllato è un tipo che estende Ada.Finalization.Controlled
(oppure Ada.Finalization.Limited_Controlled
per i tipi controllati e limitati), per il quale è possibile eseguire l'override di tre procedure (due nel caso dei tipi limitati, dove manca la procedura Adjust
):
with Ada.Finalization ;
package P is
type T is new Ada . Finalization . Controlled with
record
...
end record ;
overriding procedure Initialize ( This : in out T );
overriding procedure Adjust ( This : in out T );
overriding procedure Finalize ( This : in out T );
end P ;
La procedura Initialize
viene eseguita sull'oggetto subito dopo la creazione e può svolgere le funzionalità di inizializzazione tipicamente delegate ad un costruttore, [60] la procedura Adjust
viene eseguita subito dopo un'assegnazione (per cui non è disponibile per i tipi Limited_Controlled
) e può fungere da costruttore di copia, mentre la procedura Finalize
viene eseguita immediatamente prima della deallocazione di un oggetto, e funge da distruttore . [61]
Per ragioni storiche, i tipi Ada.Finalization.Controlled
e Ada.Finalization.Limited_Controlled
non sono interfacce (aggiunte solo in Ada 2005) ma tipi astratti, per cui non è possibile definire un tipo che sia controllato e che contemporaneamente erediti l'implementazione di un tipo non controllato. [59]
Note
- ^ John Barnes , The Ravenscar profile , su adaic.org .
- ^ S. Tucker Taft e Florence Olsen, Ada helps churn out less-buggy code , su gcn.com , Government Computer News, 30 giugno 1999, pp. 2–3. URL consultato il 14 settembre 2010 ( archiviato il 31 agosto 2015) .
- ^ Michael Feldman, Who's using Ada? , su seas.gwu.edu , SIGAda Education Working Group ( archiviato il 31 agosto 2015) .
- ^ Pulling strings 220 miles above Earth - The ISS software serves as the orbiting lab's central nervous system ( PDF ), Boeing (archiviato dall' url originale il 23 aprile 2015) .
- ^ Barnes (2014) , p. 380 .
- ^ Gary Dismukes, Gem #63: The Effect of Pragma Suppress , su adacore.com ( archiviato il 28 luglio 2015) .
- ^ Il programma, salvato nel file
hello.adb
, può essere compilato usando il compilatore GNAT con il comandognatmake hello.adb
- ^ Fanno eccezione i letterali di tipo carattere o stringa.
- ^ Barnes (2014) , p. 67 .
- ^ Barnes (2014) , p. 851 .
- ^ Barnes (2014) , p. 68 .
- ^ Barnes (2014) , pp. 73-74 .
- ^ Barnes (2014) , p. 75 .
- ^ La label come ultima riga del blocco è valida solo a partire dallo standard Ada 2012, mentre le versioni precedenti richiedevano che il
goto
fosse seguito da un'istruzione (quindi bisognava aggiungere un'istruzione nulla al termine del blocco, dopo la label). - ^ Barnes (2014) , p. 114 .
- ^ Peter Van der Linden, Expert C Programming: Deep C Secrets , prentice Hall Professional, 1994, pp. 36-38, ISBN 978-0-13-177429-2 .
- ^ Barnes (2014) , p. 11 .
- ^ Barnes (2014) , p. 211 .
- ^ Barnes (2014) , p. 83 .
- ^ Barnes (2014) , p. 87 .
- ^ Barnes (2014) , p. 18 .
- ^ Taft et al. , pp. 356-359 .
- ^ Taft et al. , pp. 319-322 .
- ^ Barnes (2014) , pp. 77-79 .
- ^ Barnes (2014) , pp. 87-89 .
- ^ Barnes (2014) , p. 117 .
- ^ Barnes (2014) , p. 112 .
- ^ Barnes (2014) , p. 137 .
- ^ Barnes (2014) , pp. 118, 135-136 .
- ^ Barnes (2014) , p. 128 .
- ^ Barnes (2014) , p. 138 .
- ^ Barnes (2014) , pp. 143-146 .
- ^ Barnes (2014) , pp. 439 ss.
- ^ Barnes (2014) , p. 251 .
- ^ In questa voce si usano distintamente i tre termini, con significato differente: "funzione" per indicare un sottoprogramma che ha un valore di ritorno, "procedura" per indicare un sottoprogramma che non ha un valore di ritorno, "routine" per indicare un generico sottoprogramma (procedura o funzione).
- ^ Barnes (2014) , pp. 180 ss.
- ^ Barnes (2014) , pp. 181-182, 185 .
- ^ Barnes (2014) , p. 169 .
- ^ Barnes (2014) , pp. 265-266 .
- ^ Barnes (2014) , p. 183 .
- ^ Barnes (2014) , pp. 272-273 .
- ^ Barnes (2014) , p. 277 .
- ^ Barnes (2014) , pp. 469 ss.
- ^ Barnes (2014) , p. 470 .
- ^ Barnes (2014) , p. 471 .
- ^ Barnes (2014) , p. 475 .
- ^ Barnes (2014) , p. 477 .
- ^ Barnes (2014) , pp. 485-491 .
- ^ Bruce Powel Douglass,Doing Hard Time: Developing Real-time Systems with UML, Objects, Frameworks, and Patterns , Addison-Wesley, 1999, p. 91 , ISBN 978-0-201-49837-0 .
- ^ Barnes (2014) , p. 787 .
- ^ CKW Grein, Preventing Deallocation for Reference-counted Types , su adacore.com , AdaCore ( archiviato il 31 luglio 2015) .
- ^ Barnes (2014) , p. 30 .
- ^ a b Barnes (2014) , p. 31 .
- ^ Barnes (2014) , p. 306 .
- ^ Barnes (2014) , p. 334 .
- ^ Barnes (2014) , pp. 34-35 .
- ^ Barnes (2014) , p. 35 .
- ^ Barnes (2014) , pp. 347-348 .
- ^ a b Barnes (2014) , p. 350 .
- ^ Tecnicamente non si tratta di un costruttore, che viene eseguito durante la creazione dell'oggetto e dopo l'esecuzione dei costruttori di eventuali superclassi.
- ^ Barnes (2014) , pp. 342-346 .
Bibliografia
- Daniel-Jean David, Il linguaggio Ada , Gruppo Editoriale Jackson, 1985, ISBN 88-7056-206-9 .
- Uno sguardo su Ada ( JPG ), in Bit , anno 6, n. 40, Milano, Gruppo Editoriale Jackson, giugno 1983, pp. 52-58, ISSN 0392-8837 .
- Ada - L'evoluzione del linguaggio - Prima parte ( JPG ), in MCmicrocomputer , n. 51, Roma, Technimedia, aprile 1986, pp. 108-110, ISSN 1123-2714 .
- Ada - L'evoluzione del linguaggio - Seconda parte ( JPG ), in MCmicrocomputer , n. 52, Roma, Technimedia, maggio 1986, pp. 110-111, ISSN 1123-2714 .
Inglese
- Mark Allen Weiss, Data Structures and Algorithm Analysis in Ada , Benjamin-Cummings Publishing Company, ISBN 0-8053-9055-3 .
- Colin Atkinson,Object-Oriented Reuse, Concurrency and Distribution: An Ada-Based Approach , Addison-Wesley, 1991, ISBN 0-201-56527-7 .
- Louis Baker, Artificial Intelligence With Ada , McGraw-Hill, ISBN 0-07-003350-1 .
- John Barnes , High Integrity Ada: The Spark Approach , Addison-Wesley, ISBN 0-201-17517-7 .
- John Barnes, Programming in Ada 2012 , Cambridge University Press, 2014, ISBN 978-1-107-42481-4 .
- John Barnes, Programming in Ada 95 , Addison-Wesley, ISBN 0-201-34293-6 .
- John Barnes,Programming in Ada plus Language Reference Manual , Addison-Wesley, 1991, ISBN 0-201-56539-0 .
- Mordechai Ben-Ari, Ada for Software Engineers , John Wiley & Sons, ISBN 0-471-97912-0 .
- Judy Bishop, Distributed Ada: Developments and Experiences , Cambridge University Press, ISBN 0-521-39251-9 .
- Grady Booch e Doug Bryan, Software Engineering with Ada , Addison-Wesley, ISBN 0-8053-0608-0 .
- Alan Burns e Andy Wellings, Concurrency in Ada , Cambridge University Press, ISBN 0-521-62911-X .
- Alan Burns e Andy Wellings, Hrt-Hood: A Structured Design Method for Hard Real-Time Ada Systems , North-Holland, ISBN 0-444-82164-3 .
- Alan Burns e Andy Wellings, Real-Time Systems and Programming Languages. Ada 95, Real-Time Java and Real-Time POSIX. , Addison-Wesley, ISBN 0-201-72988-1 .
- Norman Cohen, Ada as a Second Language , McGraw-Hill Science/Engineering/Math, ISBN 0-07-011607-5 .
- Fintan Culwin, Ada, a Developmental Approach , Prentice Hall, ISBN 0-13-264680-3 .
- Nell Dale, Chip Weems e John McCormick, Programming and Problem Solving with Ada 95 , Jones & Bartlett Publishers, ISBN 0-7637-0293-5 .
- Nell Dale, Susan Lilly e John McCormick, Ada Plus Data Structures: An Object-Based Approach , Jones & Bartlett Publishers, ISBN 0-669-41676-2 .
- John English e Fintan Culwin, Ada 95 the Craft of Object Oriented Programming , Prentice Hall, ISBN 0-13-230350-7 .
- Michael B. Feldman e Elliot B. Koffman, Ada 95 , Addison-Wesley, ISBN 0-201-36123-X .
- Michael B. Feldman, Software Construction and Data Structures with Ada 95 , Addison-Wesley, ISBN 0-201-88795-9 .
- Dean W. Gonzalez, Ada Programmer's Handbook , Benjamin-Cummings Publishing Company, ISBN 0-8053-2529-8 .
- Bruce Hillam, Introduction to Abstract Data Types Using Ada , Prentice Hall, 1994, ISBN 0-13-045949-6 .
- Simon Johnston, Ada95 for C and C++ Programmers , Addison-Wesley, ISBN 0-201-40363-3 .
- Bruce C. Krell,Developing With Ada: Life-Cycle Methods , Bantam Dell Pub Group, 1992, ISBN 0-553-09102-6 .
- David R. Musser e Alexander Stepanov, The Ada Generic Library: Linear List Processing Packages , Springer-Verlag, ISBN 0-387-97133-5 .
- Ian C. Pyle,Developing Safety Systems: A Guide Using Ada , Prentice Hall, 1991, ISBN 0-13-204298-3 .
- David Rudd, Introduction to Software Design and Development With Ada , Brooks Cole, ISBN 0-314-02829-3 .
- Bo Sanden, Software Systems Construction With Examples in Ada , Prentice Hall, ISBN 0-13-030834-X .
- Walter Savitch e Charles Peterson, Ada: An Introduction to the Art and Science of Programming , Benjamin-Cummings Publishing Company, ISBN 0-8053-7070-6 .
- Jan Skansholm, Ada 95 From the Beginning , Addison-Wesley, ISBN 0-201-40376-5 .
- Daniel Stubbs e Neil W. Webre, Data Structures with Abstract Data Types and Ada , Brooks Cole, ISBN 0-534-14448-9 .
- S. Tucker Taft , Robert A. Duff, Randall L. Brukardt, Erhard Ploedereder, Pascal Leroy e Edmond Schonberg, Ada 2012 Reference Manual , Springer-Verlag, 2014, ISBN 978-3-642-45419-6 .
- David A. Wheeler, Ada 95 , Springer-Verlag, ISBN 0-387-94801-5 .
Altri progetti
- Wikibooks contiene testi o manuali sul linguaggio Ada
- Wikimedia Commons contiene immagini o altri file su Ada
Collegamenti esterni
- ( EN ) ACM SIGAda , su sigada.org .
- ( EN ) GNU Ada Homepage , su gnuada.org .
- ( EN ) AdaPower , su adapower.com .
- ( EN ) Forum
- ( EN ) Ada Tutorial , su oopweb.com . URL consultato il 30 giugno 2004 (archiviato dall' url originale il 19 ottobre 2004) .
- ( EN ) Progetti che usano Ada , su seas.gwu.edu .
Controllo di autorità | LCCN ( EN ) sh85000774 · GND ( DE ) 4000430-2 · BNE ( ES ) XX531014 (data) |
---|