Teil 2 Funktional vs. Imperativ Funktionale Sprachen: basieren auf λ-Kalkül Konzepte Ergebnis von Berechnungen sofort weiterverarbeitet (als Argument) keine Nebenwirkungen von Operationen (zumindest theoretisch) kein Zustandsbegriff Variablenbegriff der Logik Imperative Sprachen: Zustand explizit als Menge von Variablen Programmlauf ist Zustandstransformation durch Zuweisungen Zuweisung ist Nebenwirkung anschließend an Ausdrucksberechnung imperativer Sprachen Variable ist Tripel (Behälter, Inhalt, Referenz) Behälter: Speicherplatz Inhalt: Wert Referenz: Identität der Variablen (Adresse?), oft nicht explizit zugänglich Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 1 Prof. Dr. Gerhard Goos Variable Höhere Programmiersprachen WS 2001/2002 2 Variable: Klassifikation Variable als ADT: anonyme Variable: Variable nur über Referenz zugreifbar, Referenz ist Wert einer anderen Variablen durch expliziten Konstruktoraufruf eingeführt Datentyp VARIABLE(T) Konstruktoren: create: →VARIABLE(T) write: T × VARIABLE(T) → VARIABLE(T) Operationen: read: VARIABLE(T) →T Axiome ∀x,y: T; v: VARIABLE(T): write(x,write(y,v)) = write(x,v) read(write(x,v)) = x vereinbarte Variable: Variable durch Vereinbarung v: T eingeführt gebunden an Bezeichner v implizite Variable: Variable implizit vereinbart bei erster Benutzung (Fortran, Basic, ...) bequem, aber sehr gefährlich: Schreibfehler bleiben unbemerkt Im folgenden: „Name“ bedeutet entweder „Bezeichner“ oder allgemeinere Beschreibung des Zugriffspfads zu einer Variablen, z.B. a[i], a.b.c, ... Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 3 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 4 Bindung und Lebensdauer Zugriffsrechte Zuordnung von Namen zu Objekten statische/dynamische Konstante Wert-, Bedeutungsbindung, nur eine Zuweisung zulässig (write-once Variable), statisch, dynamisch, usw., alles wie gehabt zur Übersetzungszeit oder bei Vereinbarung Lebensdauer von Variablen: nur Lesen: lokal - lokal vereinbart Zuweisungen nur in dem Modul/Klasse, der Vereinbarung enthält (read-only Variable) unbeschränkt - global vereinbart oder anonym privat: persistent - auch in anderen Programmläufen zugreifbar Lesen und Zuweisen nur in dem Modul/Klasse, der Vereinbarung enthält Zugriffsrechte beschränken den Gültigkeitsbereich von Variablenbezeichnern, nicht die Lebensdauer Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 5 Prof. Dr. Gerhard Goos Datentypen imperativer Sprachen Vorsicht: Alle Grundtypen und Reihungslängen durch Prozessoreigenschaften oder Speicherumfang beschränkt! Höhere Programmiersprachen WS 2001/2002 6 Ausdrücke Skalare Typen: Grundtypen: Integer, Float, Complex(?) mit verschiedenen Längen, Boolean, Character, meist pragmatisch definiert Aufzählungstypen mit extensionaler Definition. Zusammengesetzte Typen: definiert mit Typkonstruktoren array, record (zusätzlich set, file in Pascal) Definition neuer Typen durch den Programmierer Sonderfall Text (string): spezielle Reihung oder spezieller zusammengesetzter Typ Prozedurtypen: gegeben durch Signatur proc(partyp1,...,partypn): restyp Referenztypen: Zeiger auf Objekte anderer Typen Zeiger auf Objekte einer Klasse in oo Sprachen Spezialwert void oder nil: leerer Zeiger Sonderfälle: Vereinigungstypen, Ströme, Klassen objektorientierter Sprachen, ... Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 7 Funktionaler Anteil von imperativen Sprachen (Nebenwirkungen möglich) Problembereiche: Reihenfolge des Operandenzugriffs - ideal Reihenfolge beliebig, wegen Optimierungsmöglichkeiten, Verbot der Trickprogrammierung Reihenfolge der Operationen Berücksichtigung von Prioritäten und Klammern Def. zwingend notwendig wegen Genauigkeit numerischen Rechnens Spezialprobleme: faule oder strikte Berechnung von and und or? Berücksichtigung von Überlauf usw. bei Numerik div und mod bei negativen Operanden ... Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 8 Reihenfolge Operandenzugriff Reihenfolge Operationen Auswertungsreihenfolge links – rechts Klar bei Klammern und Operationspriorität Beispiel: i + i++ Bei ungeklammerten, gleichpriorisierten Operationen: Assoziativität Linksauswertung: 2 * i Beispiel: minint * (-1) * (-1) Rechtsauswertung: 2 * i + 1 Linksassoziativität: error wenn Codierung im Zweierkomplement, Indeterministische Auswertung Rechtsassoziativität: minint beides möglich bei unterschiedlichen Ergebnissen jedoch sinnvoller Weise verboten Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 9 Prof. Dr. Gerhard Goos Zuweisung Linke Seite := Rechte Seite Linke Seite identifiziert Behälter b Rechte Seite identifiziert Wert v Zustandstransformation: <b> := v Bedingung: Typ(b) = Typ(v) (eventuell nach Typanpassung) Zentrale zustandsändernde Operation Einfacher Sprung: goto marke Indizierter Sprung (Fortran): goto (l1,l2,...,ln; i) i [1,n] Indizierter Sprung ist maschinennaher Ersatz der Fallunterscheidung Sprung auf Markenvariable (indirekter Sprung, Fortran): markenvariable := marke; ... goto markenvariable Auch Sprünge sind Zuweisungen (an den Befehlszähler) Arithmetisches if (Fortran I,II): if (Ausdruck) marke1,marke2,marke3 Kopiersemantik (Normalfall): Zuweisung weist Kopie des Werts der RS zu, oder Operationen verarbeiten Kopie ihrer Operanden Bedeutung: h := Ausdruck; if h < 0 then goto marke1 elsif h = 0 then goto marke2 elsif h > 0 then goto marke3 end Alternative Zeigersemantik(LISP): Zuweisung und Operationen bearbeiten die Originale x := 7; y := x; x := 5 Bei Zeigersemantik gilt dann y = 5 Höhere Programmiersprachen WS 2001/2002 10 Sprunganweisung Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 11 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 12 Bedingte Anweisungen Fallunterscheidung case expr when when ... when else end Einfache bedingte Anweisung: if B then A else A' end B boolescher Ausdruck Alternative: B ganzzahlig, Test auf 0 = wahr, A, A' Anweisungsfolgen, else-Teil kann fehlen Vorsicht bei Sprachen ohne end (oder anderes Schlußzeichen): dangling else Anweisungsfolgen müssen geklammert sein ({...} oder begin...end) x_1 then A_1 x_2 then A_2 x_n then A_n A_0 Fallausdruck expr und Fallmarken: gleicher Typ integer, character oder Aufzählungstyp Fallmarke: Einzelwert, Intervall a..b oder Liste von beidem Fallmarken alle verschieden (sonst nur if-then-else-Kaskade möglich) Wenn Fallausdruck keine Fallmarke liefert und else-Teil fehlt: Leeranweisung Theoretisch führt der letzte Fall zum Programmabsturz, nicht zur Leeranweisung, vgl. Dijkstras wp-Kalkül. Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 13 Prof. Dr. Gerhard Goos Implementierung Höhere Programmiersprachen WS 2001/2002 14 Fallunterscheidung nach Typ Kaskade von bedingten Anweisungen: e := expr; if e = x_1 then A_1 elsif e = x_2 then A_2 ... elsif e = x_n then A_n else A_0 end Fallunterscheidung nach dynamischem Typ eines Objektes Sprungleiste, wenn Fallmarken aus ,,kleinem'' Intervall und dicht Vorteil: Ziel: explizit programmierte ,,Polymorphie'', Anwendung verschiedener Operationen abhängig vom Typ Beispiel: Algol 68, Ada, Sather Typkennung muß explizit oder implizit gespeichert sein erlaubt Polymorphie auch in nicht oo Sprachen Kombination von beidem kann z.B. in C, ... mit gewöhnlicher Fallunterscheidung simuliert werden, wenn die Typen als ganze Zahlen codiert sind simuliert Polymorphie auch bei nicht konformen Unterklassen Nachteil: mühsame Handprogrammierung Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 15 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 16 Schleifen Zählschleife Allgemein: for i:=u step s until o loop S end Anfangsgesteuerte Schleife while B loop S end Algol 60: for i:= u step s until o, u' step s' until o' ... do A Endgesteuerte Schleife loop S until B end Zentralgesteuerte Schleife loop A; exit when B; A'; exit when B'; A''; ... end C, C++, Java schreiben die Implementierung vor: for (init; test; erhöhe) A Zähler: in den meisten Sprachen: beliebige Variable Problem: Zähler kann versehentlich in innerer Schleife wieder benutzt oder unabsichtlich verändert werden Ada: dynamische Konstante, lokal in Schleife vereinbart, keine Änderung möglich Zählschleifen Schrittweite sollte statisch bekannt sein Schrittweite und Endwert pro Schleifenaufruf nur einmal berechnen! Schwierige Implementierung: Fehler bei u = -maxint, o = maxint vermeiden Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 17 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 18 Vorzeitiges Verlassen von Schleifen: benannte Schleifen, exit Maxint-Problematik bei Schleifen Beispiel: Vorzeitiges Verlassen von Schleifen mit break möglich Aber break wird auch zum Verlassen von Fallunterscheidungen usw. benutzt for i:=1 step k to n do print i; od Was passiert bei n = -maxint? Lösung: Markieren von Schleifen: marke_1: loop ... marke_2: loop ... if B then exit marke_1 end; ... if B' then exit marke_2 end; ... end; -- loop marke_2 end; -- loop marke_1 Was passiert bei n = -maxint-1? Verlassen einzelner, auch geschachtelter Schleifen möglich Was passiert, wenn n=maxint? Was passiert, wenn k dynamisch gesetzt wird? Betrachte k<0: Schleifenmarken nur in innerhalb der geschachtelten Schleife gültig (zusätzliche Regel über Gültigkeitsbereiche) Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 19 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 20 Duffs Trick oder: wenn in C, C++ einige breaks fehlen /* Duff's device */ int main (){ int a = 11 ; /* arbitrary number > 0 */ int n = ( a + 4 ) / 5 ; switch ( a % 5 ) { case 0: do { putchar case 4: putchar case 3: putchar case 2: putchar case 1: putchar } while ( } ( '0' ( '4' ( '3' ( '2' ( '1' --n ) ) ) ) ) ) ; das gleiche Problem etwas übersichtlicherer Code int main (){ int a = 11 ; /* arbitrary number > 0 */ int n = ( a + 4 ) / 5 ; Ausgabe: ggoos(185)% a.out 10432104321 ggoos(186)% switch ( a % 5 ) { case 0: putchar ( '0' case 4: putchar ( '4' case 3: putchar ( '3' case 2: putchar ( '2' case 1: putchar ( '1' } while ( --n ) { putchar ( '0' ) ; putchar ( '4' ) ; putchar ( '3' ) ; putchar ( '2' ) ; putchar ( '1' ) ; } ; ; ; ; ; ; printf ( "\n" ) ; } praktische Anwendung: Aufrollen von Schleifen (hier fünffach) aus Effizienzgründen, wenn tatsächliche Anzahl Durchläufe unbekannt In Java ist diese Konstruktion unzulässig, vgl. Java Language Specification, Abschnitt 14.9 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 21 Prozeduren und Funktionen Höhere Programmiersprachen WS 2001/2002 ; ; ; ; ; printf ( "\n" ) ; } Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 22 Prozedur- und Funktionsvereinbarung Terminologie echte Prozedur, Unterprogramm: Prozedur ohne Ergebnis Funktionsprozedur, Funktion, Funktionsunterprogramm: Prozedur mit Ergebnis Methode: Prozedur in oo Sprache Prozedurvariable, formale Prozedur: Variable/Parameter mit Prozedur als Wert Vereinbarung geschachtelte Prozeduren möglich (in Algol-Sprachen) keine Schachtelung in Fortran, C, oo Sprachen Aufruf parameterlos: p() oder p (uniform referent: Zugriff auf Variable/Funktionsergebnis) Argumente nach Position: p(ausdruck_1,...,ausdruck_n) Argumente mit Schlüsselwort p(Datei="file", modus=lesend) fehlende Argumente ersetzt durch Standardwerte, definiert bei Vereinbarung auch Mischung mit Positionsschreibweise erlaubt, Positionsargumente zuerst Ergebnis zugewiesen an Prozedurbezeichner: p := Ergebnis mitgeteilt durch return Ergebnis zugewiesen an Spezialvariable: res := Ergebnis Ergebnis kann ignoriert werden: Fortran, C, viele oo Sprachen Prof. Dr. Gerhard Goos ) ) ) ) ) Ausgabe: ggoos(187)% a.out 10432104321 ggoos(188)% 23 Funktion (mit Schlüsselwortparametern): p(Datei: string := "stdin", modus: Mode, pufferzahl: int := 2): Fehlermodus is A end; Parameterart kennzeichnen: kein Kennzeichen: Eingabeparameter out oder &: Ausgabeparameter inout oder &&: transienter Parameter Parameterart in manchen Sprachen auch im Aufruf gekennzeichnet Fehlerbehandlung mit ganzzahligem Fehlercode als Ergebnis oder mit Ausnahmebehandlung (später) mögliche Ausnahmen als Teil der Signatur (Java)! Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 24 Prozedur- und Funktionsaufruf Parameterübergabe Verfahren: Wertaufruf (call-by-value) Ergebnisaufruf (call-by-result) Referenzaufruf (call-by-reference) Namensaufruf (call-by-name) Anweisung: call Prozedur(ausdruck_1,...,ausdruck_n) Ausdruck: call Funktion(ausdruck_1,...,ausdruck_n) Zeitpunkt der Auswertung: Strikter (Wert-)Aufruf (strict evaluation) Fauler Aufruf (call-by-need, lazy evaluation) Ausdrücke 1 ... n heißen aktuelle Parameter Gültigkeitsbereich von Parameterbezeichnern: wie lokale Variable im Rumpf der Prozedur (in den meisten Sprachen) wie lokale Variable in einem Block, der den Rumpf umgibt schlecht, weil Parameterspezifikation im Rumpf überschreibbar zusätzlich an allen Aufrufstellen, wenn Schlüsselwortparameter benutzt werden Vorsicht: formale Prozeduren/Prozedurvariable nicht mit Schlüsselwortparametern aufrufbar! Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 25 Parameterübergabe: Prinzipien Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 26 Wert-Ergebnis- vs. Referenz-Aufruf Wertaufruf Parameter: lokale Variable, bei Aufruf mit Argument initialisiert Ergebnisaufruf Parameter: lokale Variable, bei Rückkehr an das Argument zugewiesen Argument muß Variable sein Referenzaufruf Parameter: lokale Konstante, initialisiert mit Verweis auf Argument Zugriff auf Parameter: indirekter Zugriff auf Argument (lesend/schreibend) Argument muß Variable sein Namensaufruf Argument: Funktion, die wahlweise Wert oder Verweis auf Argument liefert Parameter: initialisiert mit Argumentfunktion Jeder Zugriff auf den Parameter ruft die Funktion auf Argument muß Variable sein, wenn am Parameter zugewiesen wird Wert-Ergebnis-Aufruf: Ausgabe „0“ Referenz-Aufruf: „1“ Ausgabe y:INT := 0; proc p (x: INT); begin x := x+1; print (y); end; p(y); Strikter (Wert-)Aufruf Parameter: lokale Konstante, initialisiert mit Argument fauler Aufruf: wie strikter Aufruf, aber Initialisierung bei erstem Zugriff Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 27 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 28 Verschiedene Parameterübergabemechanismen Namensaufruf (Jensens Trick) m:INT := 1; ???: Art Parameterübergabe offen real procedure sum(i,n,x,y); value n; integer i,n; real x,y; n: INT; 2w: 2. Parameter Wertaufruf Verfahren m n j k Wert Wert/Erg. Referenz Name faul 5 2 6 7 5 6 6 10 17 6 2 2 6 7 2 4 4,2w 4,2w 10 4 proc p (??? j:INT; begin ??? k: INT): INT; begin j := j+1; real s; s:=0; for i:=1 step 1 until n do s:= s + x*y; sum:= s; end; m := m+k; p := j+k erg := sum(i,n,a[i],b[i]); end; n := p(m, m+3); Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 29 Prof. Dr. Gerhard Goos Prozeduren: Ausführungsprinzip Höhere Programmiersprachen WS 2001/2002 30 Ausnahmebehandlung Modellvorstellung, die die Sichtbarkeit und Zuordnung Bezeichner Vereinbarung regelt, auch bei rekursivem Aufruf: Reserviere Speicher auf dem Keller für Parameter (ohne Reihungen) und Organisation Kopiere Prozedurtext Ersetze alle lokalen Bezeichner, einschl. Parameter, in der Kopie durch neue Bezeichner Berechne Argumente (im Kontext des Aufrufers) und weise sie an die neu bezeichneten Parameter zu Unterprogrammaufruf (Befehl) Speichere Rückkehradresse im Keller Ausführung der Prozedurkopie Prozedurrückkehr Zuweisung der Ergebnisparameter an ihre Argumente, falls vorhanden (auch vor Rückkehr möglich) Beseitige Prozedurkopie Analoges Schema für begin-end Blöcke mit lokalen Vereinbarungen Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 31 Ziel: Fehlerbehandlung so, daß eine Anweisung (ein Block) ordnungsgemäß zu Ende geführt wird. begin ... raise overflow; ... except e when overflow then Fehlerbehandlung end Methode: Auslösen der Ausnahme (raise, eventuell implizit durch Hardware) springt auf den Beginn der passenden Fehlerbehandlung. Wenn keine Fehlerbehandlung lokal vorhanden: Suche nach Fehlerbehandlung im dynamisch umfassenden Block, eventuell unter Beendigung der Prozedur, die den Fehler enthielt. Ausnahmebehandlung wie beschrieben in Ada, Modula-3, Sather, Java Java zählt Ausnahmen zur Signatur von Klassen/Prozeduren Allgemeinere Formen der Ausnahmebehandlung, z.B. mit Wiederaufsetzen, in MESA (Xerox PARC), vgl. auch J. Goodenough, CACM Juli 1975 Vorsicht: Ausnahmebehandlung und Fehlerbehandlung über FehlercodeRückmeldung wie in C, C++ nicht nebeneinander im gleichen Programm benutzen! Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 32 Steuerparallelität Datenparallelität Mehrfädige Programmierung (nebenläufig, multithreading, multitasking): 1 erzeuge neuen Prozeß (Faden, thread) p, einschl. Speicherreservierung für Keller 2 weise p Programmstück zu (Funktionsaufruf (Normalfall), spezielle task (Ada)) 3 starte Prozeß 4 Kommunikation oder Synchronisierung mit anderen Prozessen 5 Prozeßende: Rückmeldung Ergebnis (?), Stop des Prozesses, Ende des Fadens, Ende Speicherreservierung Keller 1-3 oft zusammengefaßt zu einer Operation faden_id := fork Funktion(arg_1,...,arg_n) Kommunikation, Synchronisierung mit Hilfe von Semaphoren (gem. Speicher) oder Botschaften oder abgeleiteten Verfahren (Monitore, Fernaufruf, Rendezvous) Prozeßende: Unterscheide Vater läuft simultan weiter, Sohn informiert Vater über Prozeßende mehrere gleichzeitig gestartete Prozesse warten aufeinander, bevor Vater fortsetzt erster fertiger Prozeß beendet alle anderen Söhne und setzt Vater fort Sohn läuft unabhängig vom Vater, Vater eventuell früher fertig als Sohn Parallelzuweisung: (v_1, ... ,v_n) := (e_1, ... ,e_n) Auch Vertauschung (x,y) := (y,x) zulässig Parallele Schleife: for i:=u step s until o do in parallel a[I(i)]:=f(a[I1(i)],...,a[In(i)]) end alle (o-u+1) Durchläufe simultan ausführen, jeweils indiziert mit Prozeßnummer i. simultan: (o-u+1) parallele Prozesse auf (o-u+1) Prozessoren oder zeitlich verzahnt auf weniger Prozessoren Voraussetzung: keine Datenabhängigkeit zwischen den einzelnen Durchläufen Beispiel: Berechnung von a[i] darf nicht von der Kenntnis von a[i+1] abhängen Ausnahme: selbststabiliserende Berechnungen: korrekt, unabhängig davon, ob alter oder neuer Wert von a[i+1] benutzt Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 33 Prof. Dr. Gerhard Goos Programmstruktur, Abstraktionen Gliederung des Programms in Module, Klassen, ... Unterstützung von Abstraktionen: 34 Blockstruktur Ziele Höhere Programmiersprachen WS 2001/2002 Block (Samelson 1958): Zusammenfassung von Anweisungen und zugehörigen Vereinbarungen zu größerer Anweisung eigenständiger Gültigkeitsbereich: globale gleichbenannte Größen nicht zugänglich Block lokale Größen extern nicht sichtbar zusammengesetzte Operation: Hauptprogramm, Prozedur lokale Variable haben nur lokale Lebensdauer zusammengesetztes Objekt: Verbund benutzerdefinierter Typ: Klasse, Vererbung Programm ist Block mit geschachtelten Unterblöcken Durchsetzung des Geheimnisprinzips Abbildung der Prozeduraufrufhierarchie auf dynamische Schachtelung von Blöcken Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 35 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 36 Prozedurale Abstraktion Gliederung von Programmen Hauptprogramm: In ALGOL, Pascal, ...: umfassender Block ,,enthält'' logisch alle anderen Programmeinheiten (auch bei getrennter Übersetzung) In Fortran, C und oo Sprachen: spezielle Prozedur Parameter: Text der Kommandozeile Baumartige Gliederung in Blöcke und Prozeduren in Algol, Pascal, ... Geschachtelte Gültigkeitsbereiche (statisch) Geschachtelte Lebensdauer (dynamisch) Zugriffe auf globale Größen möglich Flache Hierarchie in Fortran, C, oo-Sprachen: Prozedur: Zusammenfassung von Anweisungen (Makro) logische Einheit: abstrakte Operation ist zusammen mit Typdefinitionen, anderen Operationen Teil einer umfassenderen Abstraktion Modul in oo Sprachen: Teil einer Klasse, d.h. eines Objekttyps Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 Module, Klassen oder Übersetzungseinheiten auf Tiefe 0 Prozeduren auf Schachtelungstiefe 1 Zugriff auf globale Größen des eigenen Moduls, Klasse, ... beschränkt Möglichkeit globaler Größen, die zu mehreren Unterprogrammen, Übersetzungseinheiten, ... gehören (Common Zonen, statische Variable) 37 Prof. Dr. Gerhard Goos Globale Variablen Höhere Programmiersprachen WS 2001/2002 38 Benannte Common Zonen Common (Fortran) oder Data (Cobol): In beliebigen Unterprogrammen (UP) möglich: Common Bereiche können benannt werden: Common /Name1/ X1,...,Xm Common /Name2/ Y1,...,Ym Common X1,...Xm Umbenennung der Variablen möglich: In UP1(...): Common X11,...,Xm1 In UP1(...): Common/Name1/ X1,...,Xm In UP2(...): Common/Name2/ Y1,...,Ym In UP2(...): Common X12,...,Xm2 ... In UPn(...): Common/Name1/ X1,...,Xm Common/Name2/ Y1,...,Ym ... In Upn(...): Common X1n,...,Xmn Unterschiedliche Typisierung möglich, z.B. statt complex zweimal real, Zusammenfassung zu Reihungen unterschiedlicher Länge, ... hierdurch auch unterschiedliche Anzahl der Variablen Jeder Name definiert Gruppe von Unterprogrammen Unterprogramm kann zu mehreren Gruppen gehören Common Zone definiert Gruppe von Ups, die sie benutzen Problem: nur eine einzige Gruppe möglich Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 39 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 40 Unterprogramme mit mehreren Einstiegspunkten Modularisierung Unterprogramme in Fortran können mehrere Prozedurköpfe enthalten mit unterschiedlicher Parametrisierung Ziel: Gruppierung mehrerer Operationen, die lokale gemeinsame Daten benutzen Gruppierung von Operationen, die gemeinsame Codestücke enthalten Alternative zum Gebrauch benannter Common Zonen: Geheimnisprinzip kontrollierter Zugang: Jede Operation soll nur auf die nicht-lokalen Größen zugreifen können, die sie logisch benötigt Abschottung: Gruppen von Operationen sollen lokal die Größen vereinbaren können, die sie benötigen; andere haben keinen Zugang Austauschbarkeit: Implementierungen von Operationsgruppen sollen austauschbar ohne Rückwirkung auf andere, solange Schnittstelle gleich bleibt Wiederverwendung: Andere sollen Operationsgruppen nur mit der Kenntnis der Schnittstelle wiederverwenden können Fortrans Unterprogramme mit mehreren Eintrittspunkten / mit benannten Common Zonen erlauben dies zu formulieren, aber ohne Zwang Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 41 Zuordnung von Operationen zu Daten Partitionierung der Prozeduren bezüglich verwendeter Bereiche Hervorhebung der Schnittstelle: Modula, Ada: Unterscheidung von Definition (Schnittstelle) und Implementierung C: .h-Datei definiert Schnittstelle oo Sprachen: Unterscheidung der öffentlich und der nur privaten Operationen Probleme: Typüberprüfung an der Schnittstelle nötig nur ein Exemplar jedes Moduls außer in oo Sprachen Prof. Dr. Gerhard Goos Programmieren im Großen 1Bearbeitungseinheiten Höhere Programmiersprachen WS 2001/2002 42 Beispiel: Keller (Integer) in C bei der Entwicklung von Programmen, Implementierung über definierte Schnittstellen (öffentliche Sicht), Konsistenzprüfung zur Übersetzungszeit, Schnittstelle 2Zugriff 3Trennung der Schnittstelle von ihrer Implementierung (private Sicht), austauschbare Implementierungen. static int *stack, mark, size; static int *realloc(int *s)...; int top(void) {return mark?stack[mark]:ERROR;}; int pop(void) {return mark?stack[mark--]:ERROR;}; #define ERROR minint extern int top(void); extern int pop(void); extern void push(int); void push(int i) {if (++mark >= size) stack=realloc(stack); stack[mark]=i; }; Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 43 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 44 Modul - ADT Implementierung Modul für ADT Keller in C Implementierung ADT = (Konstruktoren, Operationen, Axiome) Modul = Schnittstelle typedef struct stack { int *stack_impl; int mark, size; } stack; Schnittstelle (öffentliche Sicht): Definition von Konstruktoren (Typdeklaration), Operationen, int top(stack s){ return s.mark?s.stack_impl[s.mark]:ERROR;}; ... Implementierung (private Sicht): der Konstruktoren und Operationen, #define ERROR minint extern int top(stack); extern typdef stack; extern int pop(stack); extern void push(stack,int); muß Axiomen des ADTs genügen. Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 45 Prof. Dr. Gerhard Goos Generische Module Höhere Programmiersprachen WS 2001/2002 46 Generischer Keller in C Namensbildung durch Makrosubstitution Mehrsortige Algebren mit einigen unspezifizierten Sorten. Schnittstelle und Implementierung enthalten Typvariablen. Instanziierung mit konkreten Typen erzeugt Modul. Definiert durch textuelle Substitution der Typvariablen durch konkreten Typ. #define STACK (type)\ typedef struct type ##_stack {\ type *stack_impl;\ int mark, size;\ } type ##_stack;\ \ type type ##_top(type ##_stack s){\ return\ s.mark?s.stack_impl[s.mark]:ERROR;};\ ... #define TOP(type,stack) type ##_top(stack) ... Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 47 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 48 Generischer Keller in ADA Modul, Klasse und Typ Schnittstelle Modul-Definition: generic type ELTS is private; package STACKS is type STACK is private; function top(s: in STACK) return ELTS; function pop(s: in STACK) return ELTS; procedure push(s: in STACK, e: in ELTS); private type STACK is record stack impl:access array(Integer range<>)of ELTS; module M is type MT is record x1:X1, x2:X2, ... end record; proc1(m:MT,...); proc2(m:MT,...); ... end; -- M mark,size : Integer; end STACK; end STACKS; Implementierung und Instanziierung Abstrakte Klasse: module K is type KT is record x1:X1, x2:X2, ... proc(...), ... end record; end K; package body STACKS is ... end STACKS; package INT_STACK is new STACKS(ELTS=Integer); Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 49 Prof. Dr. Gerhard Goos Abstrakte vs konkrete Klasse abstract class Stack (ELTS) is top : ELTS; pop : ELTS; push (e: ELTS); end; Prof. Dr. Gerhard Goos class ArrayStack(ELTS < ORDERED(ELTS)) subtype of Stack(ELTS) is private stack_impl : ARRAY(ELTS); private mark, size : INTEGER; private realloc; top : ELTS is ... end; pop : ELTS is ... end; push (e: ELTS) is ... end; end; Höhere Programmiersprachen WS 2001/2002 50 Abstraktes Programmieren Konkrete Klasse Abstrakte Klasse Höhere Programmiersprachen WS 2001/2002 51 Typen: minimale Eigenschaften von Objekten im Kontext einer Anwendung Untertypbeziehungen: Objektmengen (Typen), die diesen Anforderungen genügen. Entspricht struktureller Konformität Typschranken für Typparameter: minimale Eigenschaften von Typen Programmieren in Termen von Schnittstellen Teilweise abstrakte Klassen: Kernmethoden Basisbausteine (abstrakt) Abgeleitete Methoden Zusammengesetzt aus Kernmethoden, können bereits in abstrakter Klasse implementiert werden Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 52 Weitere Konzepte: Namensräume und Sichtbarkeit Probleme mit Sichtbarkeiten Namensräume class A { int x; } class B extends A { int x; } Pakete (im Java Sinn, nicht im ADA Sinn), class E extands A { Zugriffskontrolle int x; Objekt, class F extends B { Klasse, Superklasse, Freundklassen int x; Paket , Freund, public void f(int x) { Metaprogrammieren, Metaklassen, Reflexion ... } } } Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 53 Prof. Dr. Gerhard Goos Überladen Höhere Programmiersprachen WS 2001/2002 54 Meta-Informationen Mehrere Methoden mit gleichem Namen, aber unterschiedlichen Signaturen Bsp: Metadaten Daten über Programme Introspektion void p(int x) void p(long x) „Programmierung zur Laufzeit“ Problem: Auflösung Reflexion Besichtigen von Metadaten zur Laufzeit Metaprogrammieren Erstellen und Modifizieren von Programmen Programme = Daten (Lisp) Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 55 Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 56 Kommentare Pragmas Pragmas sind Kommentare zur Übersetzer-/Laufzeitsteuerung eingeleitet mit speziellem Kommentarsymbol, z.B. pragma (Ada) gültig für Übersetzungseinheit, Modul/Klasse/Prozedur/Anweisung nicht an beliebiger Stelle einsetzbar Ziel: Dokumentation des Programmtexts Unterschiedliche Aufgaben: Entwicklungsdokumentation (für Test, Wartung) Schnittstellendokumentation (Moduln, Klassen, Prozeduren) Benutzerdokumentation (bei kleinen Programmen) Änderungsdokumentation und Versionskontrolle Übersetzersteuerung ??? Pragmas sind implementierungsspezifisch, nicht Teil der Sprache! Unterscheide geklammerte Kommentare (mit Schachtelungsmöglichkeit): zum ,,Auskommentieren'' Zeilenkommentare (Kommentarende = Zeilenende): Standard Beginn Zeilenkommentar nach Aufgabe gegliedert, z.B. --, --*, --**, usw. Merke: Kommentare werden während des Programmentwurfs geschrieben, oder überhaupt nicht schlechte Kommentare sind besser als keine Kommentare Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 57 Zusammenfassung Teil 2 Typen Ausdrücke Ablaufsteuerung Prozeduren, Module, Klassen Überladung, Generizität und Polymorphie Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 59 Aufgabenbeispiele: Steuerung Sprachumfang (Zulassen zusätzlicher Sprachelemente, z.B. Maschinensprache-Einschub) Feinsteuerung Speicherverteilung Steuerung Verteilung Steuerung von Testausgaben Bedingungen: Übersetzung auch dann korrekt, wenn Pragmas ignoriert werden!? Pragmas werden während Symbolentschlüsselung decodiert, daher nur reguläre Syntax! Prof. Dr. Gerhard Goos Höhere Programmiersprachen WS 2001/2002 58