Skip to main content
main-content

Über dieses Buch

genannt) sollte in einer einzigen höheren Programmiersprache program­ miert werden. Die Sprache mußte daher gleichzeitig den Anforderungen des Systementwurfs auf hoher Ebene als auch den Anforderungen der Pro­ grammierung auf niederer, maschinennaher Ebene gerecht werden. Letztere wird für diejenigen Systemteile benötigt, die in direkter Wechselwirkung mit der vorgegebenen Hardware stehen. Modula-2 entstand aus sorgfältigen Entwurfsüberlegungen als eine Sprache, die alle Möglichkeiten von Pascal enthält, diese jedoch um die wichtigen Konzepte des Moduls und der Multi­ programmierung erweitert. Da ihre Syntax mehr auf der Linie von Modula als auf der von Pascal liegt, wurde der Name Modula-2 gewählt. Im Weiteren werden wir den Namen Modula synonym für Modula-2 verwenden. Die wesentlichen Zusätze von Modula-2, bezogen auf Pascal, sind: 1. Das Konzept des Moduls und insbesondere die Möglichkeit, einen Modul in einen Definitionsteil und einen Implementationsteil aufzuspalten. 2. Eine systematischere Syntax, die das Erlernen vereinfacht. Insbesondere endet jede mit einem Schlüsselwort beginnende Struktur auch mit einem Schlüsselwort, d.h. sie ist ordentlich geklammert. 3. Das Konzept des Prozesses als Schlüssel zur Multiprogrammierung. 4. Sogenannte niedere, maschinennahe Sprachelernente, mit deren Hilfe man die strengen Regeln der Konsistenz von Typen aufbrechen kann. Sie erlauben ferner, Daten einer Modula-2-Struktur auf einen anderen Speicherbereich ohne vorgegebene eigene Struktur abzubilden. 5. Der Prozedurtyp. Er ermöglicht es, eine Zuweisung von Prozeduren an Variable dynamisch vorzunehmen. Eine erste Implementierung von Modula-2 war 1979 für PDP-ll-Rechner lauffähig. Die Sprachdefinition wurde im März 1980 als Technischer Report veröffentlicht. Seither wird die Sprache an unserem Institut täglich benutzt.

Inhaltsverzeichnis

Frontmatter

Teil 1

1. Einleitung

Dieses Buch setzt eine gewisse Kenntnis der grundlegenden Begriffe von Rechnern und ihrer Programmierung voraus. Dennoch erscheint es angebracht, mit der Erklärung einiger Konzepte und deren Terminologie zu beginnen. Wir wissen, daß — mit wenigen Ausnahmen — Programme dazu geschrieben oder, genauer gesagt, entworfen werden, sie von einem Rechner interpretieren zu lassen. Der Rechner vollzieht dann, entsprechend den vom Programm gegebenen Spezifikationen, einen Prozeß, d.h. eine Folge von Aktionen. Diesen Prozeß nennt man auch eine Berechnung.

Niklaus Wirth

2. Ein erstes Beispiel

Verfolgen wir die Schritte bei der Entwicklung eines einfachen Programms und erklären dabei sowohl fundamentale Programmierkonzepte als auch grundlegende Eigenschaften von Modula. Die Aufgabe soll sein, aus zwei gegebenen natürlichen Zahlen x und y deren größten gemeinsamen Teiler (ggT) zu berechnen.

Niklaus Wirth

3. Eine Notation zur Beschreibung der Syntax von Modula

Eine formale Sprache ist eine unendliche Menge von Folgen bestehend aus Symbolen. Die Elemente dieser Menge nennt man Sätze. Im Falle einer Programmiersprache bilden diese Sätze Programme. Die Symbole entstammen einer endlichen Menge, dem Vokabular. Die Menge aller Programme ist unendlich und nicht abzählbar. Daher definieren Regeln ihre Bildung. Nach diesen Regeln gebildete Symbolfolgen bezeichnet man als syntaktisch korrekte Programme. Die Menge der Regeln ist die Syntax der Sprache.

Niklaus Wirth

4. Die Repräsentation von Modula-Programmen

Im vorigen Kapitel wurde ein Formalismus eingeführt, mit dem im weiteren Strukturen wohlgeformter Programme definiert werden. Der Formalismus definiert jedoch lediglich die Methode, mit der Programme als Symbolfolgen — im Gegensatz zu Zeichenfolgen — aufgebaut werden. Dieser “Nachteil” ist aber durchaus beabsichtigt. Denn die Repräsentation von Symbolen (und dadurch auch Programmen) in Form von Zeichen hängt zu sehr von individuellen Implementierungen ab, als daß sie für das hohe Abstraktionsniveau einer Sprachdefinition geeignet wäre. Die Einführung einer Zwischenstufe zur Repräsentation von Symbolfolgen gewährleistet eine sinnvolle Entkopplung von Sprache und letztendlicher Programmrepräsentation, die vom verfügbaren Zeichensatz abhängt. Folglich müssen wir eine Menge von Regeln zur Repräsentation von Symbolen als Zeichenfolgen verlangen. Die Symbole des Modula-Vokabulars sind in die Klassen Namen, Zahlen, Strings, Operatoren und Begrenzer, Kommentare eingeteilt. Folgende Regeln beschreiben ihre Repräsentation im standardisierten ISO-Zeichensatz: 1.Namen (identifier) sind Folgen von Buchstaben (letter) und Ziffern (digit). Das erste Zeichen muß ein Buchstabe sein.

Niklaus Wirth

5. Anweisungen und Ausdrücke

Die Spezifikation einer Aktion wird

Anweisung

(statement) genannt. Anweisungen können interpretiert (ausgeführt) werden. Die Interpretation (Ausführung) bewirkt die Transformation des Zustands der Berechnung. Der Zustand ist durch die Gesamtheit der Werte aller Programmvariablen gegeben. Die elementarste Aktion ist die

Zuweisung

(assignment) eines Wertes zu einer Variablen. Die Zuweisung hat die Form

$ assignment = designator “:=” expression.

Niklaus Wirth

6. Kontrollstrukturen

Eine der wichtigsten Fähigkeiten von Rechnern besteht darin, daß sie Aktionen auswählen, wiederholen oder bedingt (abhängig von bereits berechneten Resultaten) ausführen können. Die Reihenfolge, in der Aktionen ausgeführt werden, ist also nicht immer mit der Reihenfolge der zugehörigen Anweisungen identisch. Die Reihenfolge von Aktionen wird durch Kontrollstrukturen festgelegt. Sie beschreiben Wiederholung, Auswahl und bedingte Ausführung vorgegebener Anweisungen.

Niklaus Wirth

7. Einfache Datentypen

Wir hatten bereits früher festgestellt, daß alle Variablen deklariert, d.h. ihre Namen im Kopf des Programms eingeführt werden müssen. Der Compiler kann so falsch geschriebene Namen entdecken und aufzeigen. Darüberhinaus ordnen Deklarationen jeder Variablen einen Datentyp zu. Der Datentyp repräsentiert Information über Variable. Im Gegensatz etwa zu ihrem Wert ist diese Information permanent. Sie wird ebenfalls dazu benutzt, Inkonsistenzen in einem Programm zu entdecken, was allein durch Untersuchung des Programmtextes geschieht, — ohne daß dieser interpretiert werden muß.

Niklaus Wirth

8. Konstanten- und Variablen-Deklarationen

Wir erwähnten bereits früher, daß alle in einem Programm benutzten Namen im Kopf des Programms deklariert sein müssen, es sei denn es handelt sich um sog. Standardnamen, die in jedem Programm bekannt sind (oder aus einem anderen Modul importiert werden).

Niklaus Wirth

9. Die Datenstruktur Array

Bisher haben wir jeder Variablen einen individuellen Namen gegeben. Dies ist unpraktisch, wenn man viele gleich zu behandelnde Variable gleichen Typs benötigt, z.B. beim Aufbau einer Tabelle von Daten. In diesem Falle wollen wir der gesamten Datenmenge einen Namen geben und die einzelnen Elemente mit einer identifizierenden Nummer bezeichnen, einem sog. Index. Man sagt, der Datentyp sei strukturiert — genauer: array-strukturiert. Im folgenden Beispiel besteht die Variable a aus N Elementen, alle vom Typ CARDINAL, und die Indizes laufen von 0 bis N - 1.

Niklaus Wirth

Teil 2

10. Prozeduren

Betrachen wir die Aufgabe, eine Menge von Daten zu verarbeiten, die aus einem Kopf und einer Folge von N ähnlichen, individuellen Einheiten besteht. Man könnte dies allgemein so schreiben ReadHeader;ProcessHeader;WriteHeader;FOR i := 1 TO N DO ReadUnit; ProcessUnit;Write(i); WriteUnitEND

Niklaus Wirth

11. Das Konzept der Lokalität

Betrachten wir nochmals die Prozedur Add des vorangehenden Beispiels. Wir stellen fest, daß die Bedeutung der Variablen i streng auf den Prozedurkörper beschränkt ist. Diese innewohnende Lokalität sollte auch explizit ausgedrückt werden. Sie läßt sich durch Deklaration von i innerhalb der Prozedur erreichen. i wird damit zu einer lokalen Variablen.

Niklaus Wirth

12. Parameter

Prozeduren können mit Parametern versehen werden. Parameter stellen die herausragende Eigenschaft dar, die Prozeduren so wertvoll macht. Betrachten wir wieder das vorangehende Beispiel der Prozedur Add. Wahrscheinlich enthält ein Programm, das die Prozedur Add benutzt, mehrere Arrays, auf welche die Prozedur anwendbar sein sollte. Die Prozedur für jeden solchen Array umzudefinieren, wäre umständlich und unelegant. Durch Einführen eines Parameters für den Array-Operanden läßt sich dies vermeiden.

Niklaus Wirth

13. Funktionsprozeduren

Bisher haben wir zwei Möglichkeiten kennengelernt, ein Resultat aus dem Prozedurkörper heraus zur rufenden Stelle zurückzugeben: das Resultat wird entweder einer nicht lokalen Variablen oder einem variablen Parameter zugewiesen. Es gibt noch eine dritte Methode, nämlich die Funktionsprozedur. Damit läßt sich ein berechnetes Resultat (als Zwischenwert) in einem Ausdruck verwenden. Der Name der Funktionsprozedur repräsentiert sowohl eine Berechnung als auch das Resultat der Berechnung. Die Prozedur-Deklaration ist dadurch gekennzeichnet, daß auf die Parameterliste eine Angabe für den Typ des Resultats folgt. Als Beispiel schreiben wir obige Potenzberechnung neu.

Niklaus Wirth

14. Rekursion

Prozeduren dürfen nicht nur aufgerufen werden, sie können selbst wiederum andere Prozeduren rufen. Da jede sichtbare Prozedur aufrufbar ist, kann eine Prozedur auch sich selbst aufrufen. Diese Selbst-Aktivierung nennt man Rekursion. Die Verwendung der Rekursion ist immer dann am Platz, wenn Algorithmen rekursiv definiert sind, vor allem aber im Falle rekursiv definierter Datenstrukturen.

Niklaus Wirth

Teil 3

15. Typdeklarationen

Eine Variablen-Deklaration spezifiziert den Typ der Variablen als ihre konstante Eigenschaft. Es kann sich dabei um einen standardisierten, primitiven oder einen im Programm selbst deklarierten Typ handeln. Typdeklarationen haben die Form

$ TypeDeclaration = identifier “=” type.

Niklaus Wirth

16. Aufzählungstypen

Ein neuer unstrukturierter Typ kann als eine

Aufzählung (enumeration)

deklariert werden. Dabei werden die zu dem Typ gehörenden Werte einzeln aufgezählt. Die Typdeklaration

T = (c1,c2, ... ,cn)

führt einen unstrukturierten Typ T ein, dessen Werte durch die n konstanten Namen c1,c2, ... ,cn benannt sind. Dies sind auch die einzigen zu diesem Typ gehörenden Werte. Die Syntax zur Deklaration eines Aufzählungstyps lautet

$ enumeration = “(“ IdentList ”)”.

Niklaus Wirth

17. Unterbereichstypen

Ist von einer Variablen bekannt (bzw. nimmt man dies an), daß sie nur Werte innerhalb eines gewissen zusammenhängenden Bereichs annehmen darf, so läßt sich dies durch Deklaration eines sog. Unterbereichstyps (subrange type) ausdrücken. Nehmen wir zum Beispiel an, daß eine Variable i nur die Werte von 1 bis (einschließlich) N annehmen darf. Wir deklarieren dann: TYPE S = [1 .. N]VAR i: S (dies kann natürlich zu VAR i: [1 .. N] abgekürzt werden).

Niklaus Wirth

18. Mengentypen

Jeder Datentyp definiert eine Menge von Werten. Im Falle eines Mengentyps S ist dies die Menge aller möglichen Mengen, die aus Elementen eines gegebenen Basistyps B bestehen. Ist zum Beispiel der Basistyp B ein Unterbereich B = [0 .. 1] und ist der Mengentyp deklariert durch S = SET OF B dann bestehen die Werte des Typs S aus den Mengen {}, {0}, {1}, {0,1}. Hat der Basistyp n unterschiedliche Werte, so besitzt ihr Mengentyp 2 hoch n Werte. {} bezeichnet die leere Menge.

Niklaus Wirth

19. Rekordtypen

In einem Array haben alle Elemente den gleichen Typ. Die Rekord-Struktur bietet im Gegensatz hierzu die Möglichkeit, eine Sammlung von Objekten als eine Einheit zu erklären, selbst wenn diese Elemente verschiedenen Typen angehören. Folgende Beispiele zeigen typische Fälle, in denen der Rekord die richtige Strukturierungsmethode ist. Ein Datum besteht aus den drei Elementen Tag, Monat und Jahr. Die Beschreibung einer Person enthält etwa den Namen, das Geschlecht, eine Identifikationsnummer und das Geburtsdatum. Folgende Typdeklarationen drücken dies aus: Date = RECORD day: [1 .. 31];mo: month;yr: CARDINALENDPerson = RECORD firstName, lastName: ARRAY [0 .. 23] OF CHARmale: BOOLEAN;idno: CARDINAL;birth: DateEND

Niklaus Wirth

20. Variante Rekords

Rekordtypen bieten noch die weitere Möglichkeit an, daß ein gegebener Rekord mehrere unterschiedliche (variante) Formen annehmen kann. Dies bedeutet, daß sich Anzahl und Art von Feldern für verschiedene Variable des gleichen Rekordtyps unterscheiden können. Es ist klar, daß diese Flexibilität schwer zu entdeckende Programmierfehler verursachen kann. Insbesondere ist es damit möglich, in einem bestimmten Programmteil eine gewisse Variante einer Variablen vorauszusetzen, während tatsächlich eine andere Variante vorliegt. Man sollte variante Rekords deshalb mit größter Vorsicht verwenden.

Niklaus Wirth

21. Dynamische Datenstrukturen und Zeiger

Array-, Rekord- und Mengen-Strukturen besitzen die gemeinsame Eigenschaft, statisch zu sein. Daraus folgt, daß Variable solcher Strukturen während ihrer gesamten Lebensdauer diese Struktur beibehalten. Für viele Anwendungen ist diese Einschränkung nicht tolerierbar. Es werden auch Datenobjekte benötigt, die nicht nur ihren Wert, sondern auch ihre Zusammensetzung, Größe und Struktur ändern. Typische Beispiele sind Listen und Bäume, die dynamisch wachsen und schrumpfen. Statt nun Listenund Baumstrukturen explizit in der Sprache vorzusehen, was für manche Anwendungen vielleicht wiederum nicht genügen würde, bietet Modula ein grundlegendes Werkzeug zur Konstruktion beliebiger Strukturen, den Typ des Zeigers.

Niklaus Wirth

22. Prozedurtypen

Bisher haben wir Prozeduren ausschließlich als Teile von Programmen betrachtet, d.h. als Texte zur Beschreibung von Aktionen auf Variable, deren Werte Zahlen, logische Werte, Zeichen, etc. sind. Wir können jedoch auch den Standpunkt einnehmen, daß Prozeduren selbst Objekte sind, die man Variablen zuweisen kann. In diesem Licht erscheint eine Prozedur-Deklaration als ein Spezialfall der Konstanten-Deklaration, wobei der Wert der Konstanten die Prozedur ist. Lassen wir zusätzlich zu Konstanten auch Variable zu, dann muß man auch Typen deklarieren können, deren Werte Prozeduren sind. Diese Typen nennt man Prozedurtypen.

Niklaus Wirth

Teil 4

23. Module

Das Modulkonzept ist jene herausragende Eigenschaft, die Modula-2 von ihrem Vorgänger Pascal unterscheidet. Wir haben Module bereits angetroffen, denn jedes Programm ist ein Modul. Die meisten Programme werden in mehrere Module aufgeteilt, wobei jeder Modul Konstanten, Variable, Prozeduren und vielleicht auch Typen enthalten kann. Objekte, die in einem fremden Modul deklariert sind, können im Modul M angesprochen werden, wenn sie M explizit durch eine Import-Liste bekannt gegeben werden. In den Beispielen der vorangehenden Kapitel haben wir Ein- und Ausgabe-Prozeduren aus Moduln importiert, die eine Sammlung häufig verwendeter Prozeduren enthalten. Diese externen Prozeduren gehören nun tatsächlich zu unserem Programm, auch wenn wir sie nicht selbst geschrieben haben und sie unabhängige Texte darstellen.

Niklaus Wirth

24. Definitions- und Implementations-Teile

Der Definitionsteil eines Moduls wird Definitionsrnodul genannt. Er enthält die Deklarationen der exportierten Objekte. Alle Arten von Objekten sind deklarierbar, doch müssen einige zusätzliche Regeln beachtet werden.

Niklaus Wirth

25. Unterteilung von Programmen in Module

Die Qualität von Programmen ist durch unterschiedliche Aspekte bestimmt und läßt sich nur schwer erfassen. Der Anwender mag ein Programm nach dessen Effizienz, Zuverlässigkeit oder bequemen Dialogführung beurteilen. Während sich die Effizienz messen läßt, hängt die Bequemlichkeit mehr vom persönlichen Urteil ab. Allzu oft sagt man, ein Programm sei einfach zu benutzen und meint eher konventionell. Der Ingenieur eines Programmes mag dessen Qualität nach seiner Klarheit und Verständlichkeit beurteilen, was wiederum schwer erfaßbare, subjektive Kriterien sind. Die Tatsache, daß man eine Eigenschaft nicht in präzisen Zahlen ausdrücken kann, ist jedoch kein Grund, diese als unwichtig abzutun. Die Klarheit eines Programms ist in der Tat enorm wichtig. Die Korrektheit eines Programms zu demonstrieren (beweisen?), besteht letztendlich darin, jemanden davon zu überzeugen, daß das Programm vertrauenswürdig ist. Wie können wir diesem Ziel näher kommen? Schließlich ist es so, daß komplizierte Aufgaben gewöhnlich komplexe Algorithmen erfordern, und dies zieht eine Myriade von Details nach sich. In diesem Dschungel von Details steckt der Teufel.

Niklaus Wirth

26. Lokale Module

Die bisherigen Module haben wir als nebeneinander angeordnete Textteile angesehen. Wir werden jedoch gleich lernen, daß Module auch textlich geschachtelt sein können. Daraus folgt unmittelbar, daß geschachtelte Module nicht separat compilierbar sind. Man nennt sie lokale Module. Ihr einziger Zweck besteht darin, Details interner Objekte zu verbergen.

Niklaus Wirth

27. Sequentielle Ein- und Ausgabe

Nützlichkeit und Erfolg höherer Programmiersprachen beruhen auf dem Prinzip von Abstraktionen und dem Verbergen jener Details, die eher zum interpretierenden Rechner als zu dem durch das Programm ausgedrückten Algorithmus gehören. Am hartnäckigsten haben sich bisher Eingabe- und Ausgabeoperationen einer Abstraktion widersetzt. Dies ist nicht verwunderlich, da Ein- und Ausgabe die Aktivierung peripherer Computereinrichtungen bedingt, deren Struktur, Funktion und Arbeitsweise sich zwischen den verschiedenen Rechnertypen stark unterscheidet. Viele Programmiersprachen enthalten eigene Anweisungen zum Lesen und Schreiben von Daten in sequentieller Form, ohne auf spezielle Geräte oder Speichermedien Bezug zu nehmen. Eine derartige Abstraktion hat viele Vorteile. Man wird aber immer wieder Anwendungen finden, die bestimmte Geräteeigenschaften ausnutzen müssen und durch Standardanweisungen der Sprache nur schlecht, wenn überhaupt, unterstützt sind. Allgemeinheit ist außerdem gewöhnlich kostspielig. Daher können Operationen, die für gewisse periphere Geräte optimal implementiert sind, bei anderen Geräten ineffizient werden. Es gibt also ein echtes Bedürfnis, die Eigenschaften bestimmter Geräte transparent zu machen, wenn Anwendungen deren effiziente Benutzung erfordern.

Niklaus Wirth

28. Bildschirmorientierte Ein- und Ausgabe

Sequentielle Ein- und Ausgabe erlaubt es, Datenelemente ohne explizite Angabe einer Position zu übertragen. Dies ist auch ein natürlicher Vorgang, wenn die Position durch das Speichermedium vorbestimmt ist. Beispiele sind ein Magnetband (nach Definition eine Sequenz) oder eine Tastatur (gibt Daten in strenger zeitlicher Reihenfolge ab) oder eine Schreibmaschine (die Positionen der Zeichen sind durch die mechanischen Bewegungen des Druckkopfes bestimmt). Selbst wenn ein Speichermedium größere Flexibilität erlauben würde, ist sequentielle Ein- und Ausgabe immer dann bequem, wenn die Struktur der Daten von Natur aus sequentiell ist. Ein Text z.B. ist von Natur aus sequentiell. Das Weglassen von Information über die Position jedes einzelnen Zeichens ist eine große Vereinfachung beim Lesen und Schreiben. Und schließlich ist sequentielle Ein- und Ausgabe auch wirtschaftlich, da sich Daten zwischen gleichzeitig laufenden Prozessen (Geräten) leicht puffern lassen. All dies erklärt, warum sequentielle Datenverarbeitung so weit verbreitet und auch empfehlenswert ist.

Niklaus Wirth

Teil 5

29. Maschinennahe (niedere) Sprachelemente

Höhere Programmiersprachen ermutigen den Programmierer, seine Programme in einer strukturierten Weise zu planen. Sie zwingen ihn sogar dazu. Strukturierte Anweisungen sorgen für eine hohes Maß an Ordnung und Klarheit im Programmtext. Strukturierte Datendeklarationen erlauben, die Daten eines Programms auf einer hohen Abstraktionsebene zu organisieren. Sie ermöglichen es, eine dem Problem angemessene Organisationsform zu wählen. Der Hauptvorteil ist zusätzliche Sicherheit gegen Fehler, da Struktur Redundanz erzeugt. Sie kann (und muß) von Implementierungen — insbesondere Compilern — dazu benutzt werden, Inkonsistenzen innerhalb von Programmen, also Verletzungen der Sprachregeln, zu entdecken. Das Konzept der Datentypen ist in dieser Hinsicht besonders leistungsfähig. Es stellt daher auch ein Hauptmerkmal höherer Programmiersprachen dar.

Niklaus Wirth

30. Nebenläufige Prozesse und Coroutinen

In diesem Kapitel führen wir Konzepte der Multiprogrammierung ein, d.h. des Programmierens mehrerer, parallel bzw. nebenläufig ablaufender Berechnungen. Die Möglichkeiten sind bewußt auf die Formulierung sog. lose gekoppelter Prozesse beschränkt. Wir schließen den Bereich eng gekoppelter Arrays von Prozessen aus, da wir diesen Anwendungsbereich für ziemlich begrenzt und spezialisiert halten. Wir beschränken die Diskussion stattdessen auf Programme zur Beschreibung mehrerer Prozesse, die relativ selten miteinander kommunizieren, und die man aus diesem Grund lose gekoppelt nennt. Selten soll bedeuten, daß die Wechselwirkung nur an einigen wenigen, wohldefinierten und explizit festgelegten Programmstellen stattfindet. Unter einem Prozeß verstehen wir eine sequentielle Folge von Aktionen. Die Programmierung, wie wir sie bisher kennengelernt haben, kann als ein Spezialfall mit nur einem einzigen Prozeß angesehen werden. Umgekehrt können wir für die Multiprogrammierung alle bisher eingeführten Techniken übernehmen. Wir müssen lediglich einige neue Möglichkeiten zur Bezeichnung nebenläufiger Prozesse und zur Beschreibung ihrer Wechselwirkung zufügen. Wir folgen in dieser Hinsicht der Tradition früherer Sprachen für Multiprogrammierung wie Modula-1 und Brinch Hansen’s Concurrent Pascal.

Niklaus Wirth

31. Geräte-Prozesse, Nebenläufigkeit und Interrupts

Im letzten Kapitel diskutierten wir Systeme mit mehreren Prozessen und die Simulation nebenläufiger Prozesse auf einem einzigen Prozessor durch Verteilen der Prozessorzeiten auf die einzelnen Prozesse (time sharing). Jetzt betrachten wir die umgekehrte Situation, in der sich mehrere Prozessoren die Ausführung eines einzigen Prozesses teilen. Schauen wir uns der Einfacheit halber einen zyklischen Prozeß an, bestehend aus einem produzierenden und einem konsumierenden Teil. Der Prozeß soll so formuliert sein:

LOOP produce(x); consume(x) END

Niklaus Wirth

Übersicht über die Programmierung in Modula-2

32. Übersicht über die Programmierung in Modula-2

Modula-2 entwickelte sich aus der praktischen Notwendigkeit nach einer allgemeinen, effizient implementierbaren Programmiersprache für Minicom­puter. Ihre Vorgänger sind Pascal und Modula. Von letzterer hat sie den Namen, das wichtige Modulkonzept und eine systematische und moderne Syntax geerbt, von Pascal das meiste Übrige, insbesondere die Datenstruk­turen, d.h. Arrays, Rekords, Variante Rekords, Mengen und Zeiger. Struk­turierte Anweisungen umfassen die vertrauten If-, Case-, Repeat-, While-, For- und With-Anweisungen. Die Syntax von Modula-2 ist so gewählt, daß jede Struktur mit einem expliziten Endsymbol schließt.

Niklaus Wirth

Backmatter

Weitere Informationen