Die Programmiersprache Ada

Aktualisiert 2001-08-30

Jeder, der sich intensiver mit RISC OS befasst, wird wohl früher oder später auf den Gedanken kommen, selbst Software entwickeln zu wollen. Standardmäßig ist in jedem RISC OS-Computer BBC BASIC mit dem integrierten Assembler enthalten, das sicherlich für die ersten Schritte reicht. Für den ambitionierten Programmierer stellt sich hingegen die Frage, welche Programmiersprache für seine zukünftigen Projekte angemessen ist. Bisher lautete die Antwort im Acorn-Bereich fast immer "C" - dieser Artikel will versuchen, die Antwort "Ada" hinzuzufügen.

Geschichtliches

Ada hat eine bewegte Geschichte hinter sich. Anfangspunkt dieser Geschichte ist die sogenannte Software-Krise, mit der sich auch das US-Verteidigungsministerium intensiv auseinandersetzte. Bei einer internen Untersuchung stellte man fest, dass nicht weniger als 1300 verschiedene Programmiersprachen innerhalb der Projekte und Aufträge des DoD (Department of Defense) verwendet werden. 1975 entschließt man sich deshalb, eine neue Sprache zu entwickeln, die den Sicherheits- und Effizienzanforderungen des DoD gerecht werden sollen. 1979 wird der Auftrag zum Design einer neuen Sprache mit Fertigstellung der vorläufigen Spezifikation an ein Team von Honeywell-Bull unter Leitung von Jean Ichbiah gegeben. Resultat war das, was unter dem Namen "Ada 80" bekannt wurde - nach der Standardisierung durch die ANSI wurde daraus "Ada 83", die erste verbreitete Version von Ada.

1988 wurde ein neues Projekt namens "Ada 9X" ins Leben gerufen, um den vorhandenen ANSI-Standard bei Bedarf zu überarbeiten. Es wurde Bedarf erkannt, insbesondere um weitreichendere Änderungen in Hinblick auf Objektorientierung durchzuführen. Ein Team von Intermetrics unter der Leitung von Tucker Taft wurde mit der Aufgabe betraut, einen neuen Sprachstandard zu entwerfen - Ergebnis ist Ada 95, welches 1995 als erste objektorientierte Sprache ein ISO-Standard wurde.

Ebenfalls 1995 wurde eines der wichtigsten Projekte in der Ada-Geschichte zum ersten Mal der Öffentlichkeit präsentiert: GNAT, der GNU Ada Translator, einer der ersten Compiler, der den Ada 95-Standard erfüllte, und zudem noch kostenfrei verfügbar war. Heute ist GNAT auf vielen Systemen verfügbar, unter anderem auch unter RISC OS.

Obwohl Ada eine ursprünglich mit militärischer Zielrichtung entwickelte Sprache war und aufgrund des "DoD Mandates" (wer einen Auftrag für das DoD durchführte, musste in Ada programmieren) zunächst auch hauptsächlich in diesem Bereich eingesetzt wurde, dauerte es nicht lange, bis sich Ada in anderen Bereichen etablieren konnte, insbesondere in sicherheitsrelevanten Bereichen wie der Flugsicherung oder der Steuerung von Kernkraftwerken.

Seit Ada 95 und der Verfügbarkeit von GNAT gibt es nun keinerlei Ausreden mehr, Ada nicht zu verwenden.

Highlights

Was also zeichnet Ada 95 als Programmiersprache gegenüber anderen aus? Zunächst einmal ist die Sprache sehr streng standardisiert worden, und der komplette Standard ist im sogenannten "Ada 95 Language Reference Manual" festgehalten - dieses ist zudem noch kostenlos downloadbar (als PostScript- und HTML-Version, auch enthalten auf der GAG-CD 2), so dass bei irgendwelchen Zweifelsfällen die Sprache betreffend sehr schnell die gültige Antwort gefunden werden kann.

Die strenge Standardisierung findet auch Ausdruck in der Validierung der Compiler. Jeder Compiler, der sich "Ada 95-Compiler" nennen will, muss eine komplette Test-Suite über sich ergehen lassen - erst wenn alle Ergebnisse korrekt sind, gilt der Compiler als "offiziell validiert". Das ist zwar keine Garantie für hohe Qualität, aber zumindest ein Anhaltspunkt.

Ada ist eine streng typisierte Sprache und hat als solche die Zielrichtung, Fehler möglichst schon zur Compile-Zeit festzustellen. Es gibt keine unsauberen Dinge wie implizite Typkonversion oder beliebige Casting-Aktionen mit beliebigem Ausgang. Zudem steht die Betriebssicherheit an erster Stelle - Ada überprüft automatisch immer Array-Grenzen und andere Wertebereiche. Sollten diese Prüfungen aus Laufzeitgründen (obwohl sie nur marginal Laufzeit kosten) unerwünscht sein, lassen sie sich durch Sprachpragmas verbieten.

Ada ist multiparadigmenfähig - das heisst, dass Ada zwar verschiedene Programmierparadigmen unterstützt (beispielsweise prozedural oder objektorientiert), dem Programmierer aber nicht vorschreibt, welches er zu benutzen hat. So ist insbesondere die Objektorientierung zwar unterstützt durch alle notwendigen Konzepte wie Vererbung und Polymorphie, allerdings ist der damit verbundene Overhead nicht zwingend, wenn man diese Konzepte nicht benötigt.

Ada ist extrem leistungsfähig. Es gibt eigentlich nichts, was es nicht gibt - egal ob Exception-Handling, generische Pakete (in C++ Templates genannt), hierarchische Paketstrukturierung, Interfacing mit anderen Sprachen (C, Fortran und Cobol), Vererbung, Polymorphie, Overloading sowohl von Funktionen und Prozeduren als auch von Operatoren, Fixpunktarithmetik, Vorkehrungen für die Systemprogrammierung (Record-Layouts können bitgenau vorgegeben werden, Adressarithmetik wird unterstützt...), drei verschiedene Stringtypen (fixe Länge, variable Länge mit fester Grenze, variable Länge) sowohl für "Standard ISO 8bit" als auch für Unicode, eine umfangreiche Systembibliothek mit zahlreichen Funktionen für Input/Output, String- und Charactermanipulationen, Kalenderfunktionen...

Ein Beispiel

Generell verfolgt Ada den Ansatz, Spezifikation von Implementierung zu trennen. Ähnlich wie C es mit den Headerfiles tut, existieren bei Ada die sogenannten ads-Files, die die specification enthalten, und die adb-Files, die den body enthalten. Innerhalb eines ads/adb-Paares können sich beliebig viele Pakete befinden. Pakete können andere Pakete "importieren" und damit auf alle Funktionen und Prozeduren, die im ads-File stehen, zugreifen - Funktionalität wird also über die ads-Files sichtbar gemacht.

Genug der trockenen Vorrede - kommen wir zu ein paar Beispielen. Die meisten dieser Beispiele sind absolut sinnfrei und sollen nur die Syntax und Semantik von Ada illustrieren.

Zunächst wollen wir mal das klassische "Hello World" aufwärmen. In Ada sieht das so aus:

(Beispiel 1)

-- das ist ein Kommentar in Ada - geht immer bis zum Zeilenende,
-- ähnlich wie // in C++ und Java
with Ada.Text_IO;

procedure Hello_World is
begin
  Ada.Text_IO.Put_Line("Hello World!");
end Hello_World;

Was kann man aus diesem Beispiel lernen? Mehr, als auf den ersten Blick zu sehen ist. "with" ist das Schlüsselwort, das Zugriff auf externe Pakete (Libraries) erlaubt. Mittels with-clause werden alle Typen, Prozeduren und Funktionen sichtbar, die im ads-File des angegebenen Paketes enthalten sind. Wie man weiterhin sieht, gibt es keinen ausgezeichneten Namen für den Einstiegspunkt in das Programm (wie main in C oder C++) - man wählt einfach einen passenden und benennt das adb-File entsprechend.

Ada verfolgt die Pascal-Philosophie und schachtelt Gültigkeitsbereiche in begin-end-Paare, allerdings mit dem zusätzlichen Vorteil, dass das "end" jeweils über einen extra Identifier verfügt, um den Referenzpunkt deutlich zu machen (im obigen Falle also den Namen der Prozedur).

Wie man sieht, wird die Standardprozedur "Put_Line" voll qualifiziert aufgerufen, mit der kompletten Pakethierarchie. Das kann durchaus lästig sein, deshalb verfügt Ada zusätzlich über das "use"-Kommando, um Library-Prozeduren und Typen direkt sichtbar zu machen. Im obigen Falle könnte sich das folgendermaßen auswirken:

with Ada.Text_IO;
use Ada.Text_IO;

procedure Hello_World is
begin
  Put_Line("Hello world!");
end Hello_World;

Wie man sieht, ist die Prozedur Put_Line aus dem Paket Ada.Text_IO nun direkt sichtbar.

Um einen Vergleich mit dem Java-Package-System zu ziehen: in Java ist quasi immer in implizites "with" bereits vorhanden, alle Packages sind immer über absolute Qualifizierung sichtbar. Dadurch ist aber leider eine Eindeutigkeit des Namensraumes erforderlich, was Java über eine Namenskonvention löst - meiner Meinung nach unschön und vor allem unnötig, wie man am Beispiel von Ada sehen kann.

Als nächstes und letztes Beispiel will ich einfach einen Einblick in die Syntax von Ada geben, ohne weitere großartige Erläuterungen. Menschen mit Programmiererfahrung in einer nahezu beliebigen Hochsprache werden trotzdem verstehen, was gemeint ist. Diverse Dinge wären auch eleganter lösbar, würden dann aber die Syntax nicht in der Richtung verdeutlichen, die ich angestrebt habe.

(File: adb.Beispiele)

with Ada.Text_IO, Unchecked_Deallocation;

package body Beispiele is

Numerische_Konstante : constant := 5136;
Hex_Konstante : constant := 16#3FF8#;

type Ampel_Farben is (rot,gelb,gruen);

type List_Element;
type List_Element_Ptr is access List_Element;
type List_Element is
  record
    Zahl    : Integer := 15;
    Zeichen : Character := 'A';
    next    : List_Element_Ptr := null;
  end record;

dubiose_exception : exception;

procedure FreeListElement is 
  new Unchecked_Deallocation (List_Element,List_Element_Ptr);


function Ampeln return Integer is

  type My_Small_Integer is range 0..50000;

  Rueckgabe : My_Small_Integer;

begin
  for i in Ampel_Farben'Range loop
    case i is
      when rot   => Ada.Text_IO.Put_Line("Ampel ist rot.");
                    Rueckgabe := 0;
      when gelb  => Ada.Text_IO.Put_Line("Ampel ist gelb.");
                    Rueckgabe := 3;
      when gruen => Ada.Text_IO.Put_Line("Ampel ist grün.");
                    Rueckgabe := 2#11001010#;
      when others => raise dubiose_exception;
    end case;
  end loop;
  return Integer(Rueckgabe);
exception
  when dubiose_exception => Ada.Text_IO.Put_Line("Dieser Zweig kann nie " &
                            "ausgeführt werden, sonst hätte der Compiler" &
                            " oder das Laufzeitsystem schon gemeckert.");
                            return 0;
  when others => Ada.Text_IO.Put_Line("Irgendwas ist schiefgelaufen..." &
                                      "Exception wird nach oben gegeben!");
                 raise;
end Ampeln;


procedure Ausgabe (Text             : in String;
                   Length_of_text   : out Integer;
                   Length_of_output : in Integer := 0) is
begin
  if Length_of_output = 0 then
    Ada.Text_IO.Put_Line("Keine Ausgabe erlaubt!");
  else
    Ada.Text_IO.Put_Line(Text);
  end if;
  Length_of_text := Text'Length;
end Output;


procedure Mein_Beispiel is

Rueckgabewert : Integer;
Textlength : Integer;

begin
  Rueckgabewert := Ampeln;
  Output("TestText",Textlength);
  Output("TestText",Textlength,6);
  Output(Text => "Beispiel mit benannter Zuweisung",
         Length_of_text => Textlength,
         Length_of_output => 30);
end Mein_Beispiel;


procedure Listen_Beispiel is

anker,ptr : List_Element_Ptr;

begin
  -- Liste aufbauen
  anker := new List_Element;
  ptr := anker;
  ptr.Zahl := 38;
  ptr.next := new List_Element'(Zahl => 10,
                               Zeichen => 'C',
                               next => new List_Element);
  ptr := ptr.next.next;
  ptr.Zahl := 556325;
  -- Liste ausgeben
  ptr := anker;
  while ptr /= null loop
    Ada.Text_IO.Put_Line("Die Zahl lautet: " & Integer'Image(ptr.Zahl));
    ptr := ptr.next;
  end loop;
end Listen_Beispiel; -- die dynamisch allokierten Elemente bestehen weiterhin!

procedure Beispiel is
begin
  Mein_Beispiel;
  Listen_Beispiel;
end Beispiel;

end Beispiele;

(File: ads.Beispiele)

package Beispiele is

procedure Beispiel;

end Beispiele;

(File: adb.Test - dieses ist das "Hauptprogramm", das mit der Library "Beispiele" arbeitet; compiliert wird der ganze Sermon durch "gnatmake Test")

with Beispiele;

procedure Test is
begin
  Beispiele.Beispiel;
end Test;

Nun, genug davon. Wer sich eingehender mit Ada beschäftigen will, dem sei hier die GAG-CD 2 empfohlen - darauf befinden sich unter anderem das Ada Language Reference Manual, das Ada Rationale (fast eine Art Lehrbuch, das die Features von Ada 95 im Einzelnen beschreibt) und das Lovelace Tutorial in HTML. Insbesondere letzteres sei empfohlen für alle, die sich an Ada versuchen wollen - bei weitergehender Beschäftigung seien die diversen Bücher empfohlen, die am Ende dieses Artikels besprochen werden.

Ada im RISC OS-Kontext

Der einzige Ada 95-Compiler, der für RISC OS verfügbar ist, ist der GNAT. Gott sei Dank ist das keine erhebliche Einschränkung - GNAT gilt als einer der besten verfügbaren Ada 95-Compiler und wird im OpenSource-Modell von ACT (Ada Core Technologies) ständig weiterentwickelt.

Wie unter RISC OS leider üblich, ist eine integrierte Entwicklungsumgebung nicht in Sicht. Dafür gibt es aber sowohl für StrongED als auch für Zap einen Ada-Modus, der Syntax-Colouring sowie ein paar nützliche Funktionen beherrscht.

Bei den verfügbaren Bibliotheken sieht es im Moment etwas dünn aus - prinzipiell lässt sich mit einem geeigneten Tool und der Möglichkeit von Ada, über das C-Interface zu kommunizieren, nahezu jede C-Bibliothek mit endlichem Aufwand zu einer Ada-Bibliothek machen, allerdings handelt es sich damit natürlich nur um eine sogenannte "thin binding", d.h. die Ada-typischen Abstraktionen finden sich hier nicht, sondern es ist eine 1:1-Umsetzung der C-Vorlage. Das Gegenteil nennt man übrigens "thick binding", und genau eine solche wird derzeit von mir entwickelt. Sie entsteht in Zusammenhang mit CDBurn und wird frei verfügbar sein. Eine sehr frühe Version, die noch sehr stark an BASIC- oder C-Bibliotheken erinnert, ist bereits auf der GAG-CD 2 vorhanden. Eine Art Tutorial nach dem Motto "meine erste Ada-WIMP-Applikation" wird gerade von mir vorbereitet. Wer sich freiwillig melden will, um zu helfen, ist jederzeit willkommen.

Debugging ist schon immer ein wunder Punkt unter RISC OS gewesen. Da noch keiner GDB auf RISC OS portiert hat, mit dem ein Source-Level-Debugging von GNAT-Code möglich ist, ist man derzeit auf DDT im Assembler-Modus angewiesen. Damit kann man ganz gut leben - ich lebe sogar völlig ohne Debugger, was dank Adas außerordentlich strenger Compilierung eigentlich kein Nachteil ist - die typischen C-Fehler wie dereferenzierte Null-Pointer, Speicherlecks, Variablen- und Arrayüberläufe entstehen hier erst gar nicht.

Wer unter C oder C++ schon immer auf Kriegsfuß mit den fehlerträchtigen Makefiles gestanden hat, kann sich jedenfalls beruhigt zurücklehnen. GNAT bietet die Möglichkeit der vollständigen Überprüfung von Abhängigkeiten und bedingten Recompilierung. Mittels eines einfachen Aufrufs

gnatmake !RunImage

werden beispielsweise bei mir die entsprechend geänderten Sourcefiles von CDBurn neu compiliert. Das Ganze verpackt in ein Obey-File, und schon vermisst man eine integrierte Umgebung nicht mehr ganz so stark.

Wo Licht ist...

Natürlich birgt Ada auf einem RISC OS-Rechner auch ein paar Nachteile, die man kennen sollte, bevor man sich in das "Abenteuer Ada" stürzt.

Zunächst ist GNAT nicht eben der schnellste Compiler - ein kompletter Rebuild von CDBurn dauert schon seine Zeit. Man kann die Problematik natürlich entsprechend abschwächen, indem man seine Pakete intelligent designed und möglichst wenige Abhängigkeiten zwischen diesen einbaut, aber trotzdem bleibt natürlich ein gewisses Performance-Hindernis.

Ein weiteres Hindernis ist der extreme Speicherbedarf von GNAT. 3.6 MB fürs Taskwindow, dazu nochmal 4-20 MB in einer dynamic area bei einigermaßen großen Paketen - da sollte der Risc PC schon mit 32 MB ausgestattet sein. Gott sei Dank funktioniert GNAT auch in Zusammenarbeit mit Virtualise von Clares, und zudem ist RAM ja so billig, dass 64 MB kein Hinderniss sein dürften - dann kann man die GNAT-eigenen Pakete auch in der RAM-Disk halten, was den Compiliervorgang erheblich beschleunigen kann.

GNAT selbst ist eine relativ alte Version - auf anderen Systemen ist man schon bei 3.13 (public release), auf RISC OS ist es noch 3.03. Obwohl schon diese Version eine sehr hohe Qualität erreicht, sind die neueren Versionen, auch was die Optimierung angeht, deutlich weiter fortgeschritten.

Es gibt aber Hoffnung, dass demnächst eine aktuelle GNAT-Version unter RISC OS zur Verfügung stehen wird. Das kommt daher, dass GNAT demnächst wieder in die aktuelle GCC-Version eingepflegt wird und nicht mehr länger auf einer Spezialversion von GCC 2.8.1 basiert - vermutlich wird das ab GCC 3.1 der Fall sein. Da ich gleichzeitig die alten Recken (Nick Burrett et al.) neu motiviert habe um den GCC zu portieren (siehe Homepage der GCC for RISC OS initiative und Homepage des neuen GCC-Ports und UnixLib), wird so eventuell durch die Hintertür ein neuer GNAT auf uns zukommen.

Ada im Internet

Hier ein paar Einstiegspunkte für allerlei Ada-Resourcen im WWW:

  • Home of the brave Ada Programmer - nahezu alles, ausführliche Reviews von Büchern und Tools, Online-RM, Linksammlung, Softwaresammlung...seit 1998 nicht mehr aktualisiert, aber immer noch einen Besuch wert

    Als Newsgroup ist comp.lang.ada verfügbar. Im Gegensatz zu den einschlägigen Programmiersprachennewsgroups sind hier eine Menge Experten versammelt, die wirklich jede Frage, die irgendwo das Wort Ada enthält, fachkundig beantworten können. Zu den regelmäßigen Teilnehmern gehören beispielsweise Robert Dewar (einer der führenden Köpfe hinter GNAT) und Tucker Taft (der Leiter der Ada 95-Entwicklung und Mitarbeiter bei AverStar, einem der führenden Ada-Compilerhersteller).

    Literatur

    Leider habe ich bisher keine deutsche Ada-Literatur gelesen, kann also nicht guten Gewissens Empfehlungen dafür oder dagegen aussprechen - dafür sind die von mir gelesenen englischen Bücher von durchweg sehr guter Qualität. Hier eine Auswahl an Büchern mit ein paar Anmerkungen:

    Norman H. Cohen: Ada as a second language (2nd edition), McGraw Hill, 1133 Seiten, ca. 130 DM. Ein absolutes Mega-Werk, als Referenz quasi unverzichtbar. Als Lehrbuch weniger geeignet, da Programmierkenntnisse vorausgesetzt werden. Im Buch werden öfter interessante Vergleiche zu anderen Programmiersprachen gezogen. Für mich ist dieses Buch ein absolutes Muss, ich benutze es während der Programmierung praktisch ständig als Nachschlagewerk.

    Michael A. Smith: Object-Oriented Software in Ada 95, Thomson Computer Press, 459 Seiten, ca. 65 DM. Ein echtes Lehrbuch, mit einem gewissen Fokus auf die objektorientierten Features von Ada 95. Dinge wie Tasking werden nur am Rande erwähnt, das Interfacing zu anderen Sprachen wird praktisch gar nicht behandelt. Störend sind die vielen Tippfehler. Das Buch enthält als Abschluss eines jeden Kapitels ein paar Übungen zur Selbstüberprüfung.

    Michael B. Feldman, Elliot B. Koffman: Ada 95 Problem solving and Program Design, Addison-Wesley, 815 Seiten, ca. 70 DM. Mein Favorit unter den Lehrbüchern. Sehr leicht verständlich und meines Erachtens intelligent aufgebaut. Zu Anfang sieht es so aus, wie wenn die Objektorientierte Programmierung nur stiefmütterlich behandelt werden würde - aber am Ende des Buches merkt man, dass alle Konzepte der Objektorientierung praktisch in Fleisch und Blut übergegangen sind. Ein Hauptaugenmerk liegt auf universellen Datenstrukturen, die dann auch gleich in vielen praktischen Beispielen ("case studies") eingesetzt und vertieft werden. Am Ende eines jeden Kapitels gibt es Testfragen und Übungsaufgaben zur Selbstkontrolle und Vertiefung. Didaktisch das beste Ada-Buch, das ich kenne, und dabei trotzdem ausführlich genug. Kommt mit einer CD-ROM, die für Windows einen ready-to-run Ada-Compiler enthält.

    John Barnes: Programming in Ada 95 (2nd edition), Addison-Wesley, 700 Seiten, ca. 80 DM. John Barnes hat am Standardisierungsprozess von Ada 95 aktiv teilgenommen - in diesem Buch erfährt man daher wie in keinem zweiten die Philosophie, die hinter Ada 95 steckt. Als Einsteiger-Buch nicht unbedingt empfehlenswert, da kaum vollständige Programme gezeigt werden und auch der "rote Faden" mit einfachen Beispielen fehlt. Für den fortgeschrittenen Ada-Programmierer ist es meines Erachtens aber unverzichtbar, um die Feinheiten der Sprache kennenzulernen.

    Michael B. Feldman: Software Construction and Data Structures with Ada 95, Addison-Wesley, 650 Seiten, ca. 70 DM. Ein sehr gutes Buch, das anschaulich erläutert, wie eine vernünftig organisierte Software-Entwicklung ablaufen sollte. Ganz nebenbei wird das Handwerkszeug für die Laufzeitanalyse von Programmen erklärt, und eine Menge wiederverwendbarer abstrakter Datentypen anschaulich entwickelt - von der einfachen Liste über nahezu beliebige Graphen bis hin zu Sortiermethoden und Hash-Tables geht die Palette. In der typischen Art von Feldman geschrieben und daher sehr leicht verständlich.

    Zum Abschluss noch ein Hinweis auf ein Buch, das für den gemeinen Acorn-Programmierer möglicherweise nicht von so großer Bedeutung ist - aufgrund seiner überzeugenden Qualität will ich es aber nicht unerwähnt lassen.

    Alan Burns, Andy Wellings: Concurrency in Ada (2nd edition), Cambridge University Press, 390 Seiten, ca. 65 DM. Ein herausragendes Buch über parallele Programmierung mit Implementierungsschwerpunkt Ada 95. Man merkt dem Buch an, dass es von zwei alten Hasen auf diesem Gebiet geschrieben wurde - und trotzdem bleibt alles, gemessen an der Komplexität der Materie, leicht verständlich.
     


    Home © 1999-2001 Steffen Huber, steffen@huber-net.de

    Valid HTML 4.01!