Ada è un linguaggio di programmazione sviluppato verso la fine degli anni settanta su iniziativa del Dipartimento della Difesa (DOD) degli Stati Uniti. Sia le specifiche che lo sviluppo del linguaggio furono affidati a bandi di gara. Tra le 17 proposte inviate in seguito al bando indetto dal DOD, fu scelto nel 1979 il progetto di Jean Ichbiah, che all'epoca lavorava presso la CII Honeywell Bull. Le specifiche divennero uno standard ANSI e ISO nel 1983, seguito dalle successive revisioni nel 1995, 2005 e 2012. Un sottoinsieme hard real-time del linguaggio è noto come profilo Ravenscar.
Ada combina principi e tecniche provenienti da diversi paradigmi di programmazione, in particolare programmazione modulare, programmazione orientata agli oggetti, programmazione concorrente e calcolo distribuito. Sebbene l'interesse del DOD vertesse principalmente sullo sviluppo di applicazioni militari, Ada è un linguaggio general purpose che si presta all'utilizzo in qualsiasi dominio applicativo. L'origine militare si rivela però nella presenza di caratteristiche fortemente orientate alla sicurezza del codice; per questo motivo, il linguaggio viene ancora oggi usato in molti contesti in cui il corretto funzionamento del software è critico, come astronautica, avionica, controllo del traffico aereo, finanza e dispositivi medici.
I compilatori Ada impiegati per lo sviluppo di software mission-critical devono seguire un processo di certificazione secondo lo standard internazionale ISO/IEC 18009 (Ada: Conformity Assessment of a Language Processor), implementato nella suite Ada Conformity Assessment Test Suite (ACATS), parte integrante del processo di certificazione svolto da laboratori autorizzati dall'Ada Compiler Assessment Authority (ACAA).
Il nome iniziale del linguaggio doveva essere DOD-1, ma venne in seguito cambiato in Ada in onore di Ada Lovelace, illustre matematica dei primi anni del XIX secolo, accreditata come la prima programmatrice della storia per aver sviluppato un algoritmo per il calcolo dei numeri di Bernoulli sulla macchina analitica di Charles Babbage.
Caratteristiche Ada eredita alcune caratteristiche stilistiche fondamentali da ALGOL, rispetto al quale aggiunge molte funzionalità basilari (come il sistema di tipi, i record, i puntatori o le enumerazioni, implementati in buona parte in stile Pascal) e funzionalità avanzate proprie dei moderni linguaggi di programmazione (polimorfismo, ereditarietà, eccezioni, tasking).
Il linguaggio fornisce un gran numero di controlli sia statici (a tempo di compilazione) sia dinamici (a runtime), che prevengono un'ampia varietà di errori (uso errato dei parametri, errori di tipo, violazione di range e off-by-one). I controlli dinamici sono disattivabili se si vuole massimizzare l'efficienza, tramite il pragma Suppress,. o tramite switch specifici dei vari compilatori. Sicurezza e affidabilità del codice sono infatti uno dei principali aspetti che hanno guidato lo sviluppo del linguaggio.
"Hello, world!" in Ada Un Hello world in Ada è il seguente:Il programma, salvato nel file hello.adb, può essere compilato usando il compilatore GNAT con il comando gnatmake hello.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin Put_Line("Hello, world!"); end Hello;
Sintassi A differenza della maggior parte dei linguaggi di programmazione, Ada è insensibile alle maiuscole.Fanno eccezione i letterali di tipo carattere o stringa. Le convenzioni stilistiche più comuni prevedono di scrivere le keyword del linguaggio interamente in minuscolo (o, meno comunemente, interamente in maiuscolo) e i nomi di tutti gli identificatori (tipi, variabili, subroutine, package etc.) in snake case con l'iniziale di ogni parola maiuscola. I commenti sono su singola linea, iniziati da un doppio trattino -- e terminati dal ritorno a capo. Per gli identificatori e i commenti Ada supporta il set di caratteri ISO 10646, permettendo quindi di scrivere codice in caratteri non ASCII, e la lunghezza massima consentita per gli identificatori è legata all'implementazione (nelle implementazioni standard deve essere pari a non meno di 200 caratteri)..
La sintassi di Ada impiega pochi simboli, prediligendo l'uso di parole in lingua inglese. I simboli sono l'assegnazione :=, gli operatori aritmetici elementari (+, -, *, / e **), gli operatori di comparazione (<, <=, >, >=, =, /=), i due punti : per dichiarare il tipo di una variabile, la freccia => negli aggregati, la virgola , come separatore negli aggregati, l'operatore di accesso ai campi ., l'indicazione di range .., il tick ' per accedere agli attributi, il box <> per indicare un parametro variabile nelle dichiarazioni, il punto e virgola ; per separare i parametri di una routine e per terminare le istruzioni. L'istruzione nulla è costituita dalla keyword null terminata da punto e virgola, mentre una riga vuota terminata da punto e virgola non è valida. I restanti operatori sono implementati tramite keyword (and, or, rem, mod etc.).
Ada è un linguaggio strutturato e i blocchi sono delimitati da keyword. La chiusura del blocco contiene un riferimento o identificatore per capire immediatamente a quale apertura appartiene ed evitare confusione, impedendo inoltre potenziali dangling else o analoghi errori. Ad esempio, una subroutine contenente un ciclo for appare come:
procedure Example is X: array (Integer range 1..5) of Integer; begin for I in X'Range loop X(I) := I; end loop; end Example;
Parole riservate Il linguaggio, in riferimento allo standard Ada 2012, ha 73 parole riservate:.
abort abs abstract accept access aliased all and array at begin body case constant declare delay delta digits do else elsif end entry exception exit for function generic goto if in interface is limited loop mod new not null of or others out overriding package pragma private procedure protected raise range record rem renames requeue return reverse select separate some subtype synchronized tagged task terminate then type until use when while with xor
Esiste un'omonimia tra le parole riservate access, delta, digits, mod e range e gli omonimi attributi, ma essendo gli attributi sempre preceduti da un apostrofo (detto tick) non esiste rischio di ambiguità..
Dichiarazioni di variabile Le dichiarazioni di variabile in Ada si effettuano indicando il nome dell'entità dichiarata, seguito da : e poi dal tipo, quest'ultimo preceduto da eventuali specificatori (constant, aliased, not null etc.). Un valore di inizializzazione statico o dinamico può essere indicato facoltativamente dopo il tipo, separato da :=, e la dichiarazione è infine terminata da ;. Le dichiarazioni possono essere collocate nella specifica di un package o nella parte dichiarativa di una routine o di un blocco declare. Più variabili possono essere dichiarate nella stessa dichiarazione, separando i nomi con virgole, ma si tratta solo di zucchero sintattico e tecnicamente le dichiarazioni sono comunque distinte ed indipendenti fra loro, quindi ad esempio un'eventuale espressione di inizializzazione viene valutata una volta per ciascuna variabile..
È possibile definire variabili costanti facendo precedere il tipo dalla keyword constant, nel quale caso è obbligatorio fornire un'inizializzazione, ed è inoltre possibile definire costanti numeriche omettendo il tipo prima dell'inizializzazione, che deve consistere in un'espressione statica, ovvero nota a tempo di compilazione (il tipo della costante viene inferito dall'inizializzatore letterale). La differenza tra variabili costanti e costanti numeriche consiste nel fatto che le prime sono variabili calcolate a runtime, mentre le seconde vengono risolte a tempo di compilazione..
-- variabile intera N: Integer;
-- due variabili intere, inizializzate con un valore casuale -- (possono assumere due valori diversi) I, J: Integer := Random(Seed);
-- variabile costante (valutata a runtime) F: constant Float := Float(I + J);
-- costante numerica (risolta staticamente a tempo di compilazione) π: constant := 3.14159_26535_89793_23846;
Goto A differenza di molti linguaggi moderni, Ada conserva l'istruzione goto. Pur essendo generalmente deprecata nella programmazione strutturata, è infatti un'istruzione utile per la generazione automatica di codice a partire da sorgenti in altri linguaggi o specifiche formalizzate ad alto livello. È inoltre accettabile in alcuni contesti, come il salto verso il termine di un bloccoLa 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). (ad esempio un'iterazione di un ciclo) o l'uscita da cicli profondamente annidati,. contesto nel quale è più leggibile rispetto ad analoghe istruzioni break o continue in altri linguaggi in quanto il punto di arrivo del salto nel codice è chiaramente indicato dalla label (mentre il break in linguaggi come il C può essere error prone).
procedure Print_Integers is begin for I in 1..20 loop Put(Integer'Image(I)); if I mod 5 = 0 then New_Line; goto Continue; -- goto end if; Put(", "); <<Continue>> -- label end loop; end Print_Integers;
Sistema di tipi
Ada è un linguaggio fortemente tipizzato e typesafe.. A differenza del C e dei suoi derivati, Ada non ammette conversioni di tipo implicite (tranne che per i tipi universali e gli access type anonimi). e la conversione di tipo si effettua scrivendo il nome del tipo seguito dalla variabile da convertire tra parentesi., ad esempio:
procedure Conversion is X: Float := 2.9; Y: Integer; begin Y := X; -- illegale (assegna valore Float a variabile Integer) X := X + 1; -- illegale (l'operatore + non è definito su tipi misti) X := X + 1.0; -- legale Y := Integer(X); -- conversione di tipo (con arrotondamento): ora Y vale 3 end Conversion;
Il tipo di un letterale può essere indicato esplicitamente con una sintassi simile alla conversione, aggiungendo un tick prima della parentesi aperta. Questo è utile soprattutto in caso di ambiguità, quando uno stesso letterale (ad esempio una stringa, o un valore enumerativo) può riferirsi a tipi diversi..
Tipi predefiniti A differenza del C e dei suoi derivati, in Ada non esistono keyword che identificano tipi primitivi, e tutti i tipi predefiniti sono definiti nella standard library. I tipi predefiniti fondamentali (come Integer, Float o Character) sono definiti nel package Standard, ma per massimizzare la portabilità è considerata buona pratica non usare direttamente i tipi predefiniti e definire invece i propri, anche per i tipi numerici più semplici..
I tipi definiti nel package Standard sono sempre visibili in ogni parte del programma, mentre gli altri tipi definiti nei restanti package della libreria standard richiedono una clausola with per essere visibili. I tipi definiti in Standard sono:. Integer: tipo discreto intero, che assume valori in un intervallo di estensione legata all'implementazione, non inferiore a .. . Natural: sottotipo di Integer che può assumere solo valori non negativi; Positive: sottotipo che può assumere solo valori positivi non nulli; Float: tipo in virgola mobile con almeno sei cifre; Duration: tipo in virgola fissa, usato per esprimere un tempo in secondi; Character, Wide_Character, Wide_Wide_Character: tipi speciali di enumerazione, usati per i caratteri di testo con codifica rispettivamente a 8, 16 e 32 bit (gli ultimi due sono stati aggiunti rispettivamente in Ada 95 e in Ada 2005)