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