Reformatted Errorhandler Article

This commit is contained in:
Carsten Strotmann 2020-07-15 10:16:59 +02:00
parent 449712dcce
commit cafe4b5ca6
3 changed files with 238 additions and 437 deletions

View File

@ -2,14 +2,9 @@ ERR.ART
Korrektur clv03jul89 Korrektur clv03jul89
Entwurf clv01mar88 Entwurf clv01mar88
set margins 1 40
(mit c-t in Kommandozeile)
Titel: Titel:
Behandlung von Ausnahmesituationen in Behandlung von Ausnahmesituationen in Forth83
Forth83
Stichworte: Stichworte:
@ -19,194 +14,114 @@ exception handling
volksFORTH83 volksFORTH83
returnstack returnstack
Kurzfassung: Kurzfassung: Ausgehend von einer Analyse des Bedürfnisses nach
Ausgehend von einer Analyse programmspezifische Fehlerbehandlung (die insbesondere zum erweiterten
des Bed<65>rfnisses nach Begriff des 'Exception handling' führt) werden Konzepte aus
programmspezifische Fehlerbehandlung verschiedenen Programmiersprachen sowie zu Forth83 vorgeschlagene
(die insbesondere zum erweiterten Konzepte auf ihre Brauchbarkeit hin diskutiert. Es folgt eine unter
Begriff des 'Exception handling' f<>hrt) ultraFORTH83 rev 3.8 auf einem C16 entwickelte Lösung des Autors, die
werden Konzepte aus verschiedenen Programmiersprachen abhängig von der Ausführungsebene eine spezielle mittels FAILS..THEN
sowie zu Forth83 vorgeschlagene Konzepte installierte Behandlung der Worte ABORT" und ERROR" gestattet.
auf ihre Brauchbarkeit
hin diskutiert. Es folgt eine unter
ultraFORTH83 rev 3.8 auf einem C16
entwickelte
L”sung des Autors, die abh„ngig von
der Ausf<73>hrungsebene eine spezielle
mittels FAILS..THEN installierte
Behandlung der Worte ABORT" und ERROR"
gestattet.
o Die derzeitige Fehlerbehandlung * Die derzeitige Fehlerbehandlung in Forth: ABORT"
in Forth: ABORT"
Im 83er-Standard ist das zentrale Wort Im 83er-Standard ist das zentrale Wort zur Fehlerbehandlung ABORT". Es
zur Fehlerbehandlung ABORT". Es gibt den folgenden String als Fehlernachricht aus, versetzt das System
gibt den folgenden String als in einen (einigermaßen) definierten Zustand und ruft das
Fehlernachricht aus, versetzt das System Top-Level-Wort QUIT auf, das Eingaben von der Tastatur entgegennimmt
in einen (einigermaáen) definierten und verarbeitet. Jedes laufende Programm wird also ohne Rücksicht auf
Zustand und ruft das Top-Level-Wort QUIT Verluste gestoppt und gewissermaßen Forth neu gestartet. Eine ähnliche
auf, das Eingaben von der Tastatur Wirkung haben die Worte ABORT und QUIT.
entgegennimmt und verarbeitet.
Jedes laufende Programm wird also ohne
R<EFBFBD>cksicht auf Verluste gestoppt und
gewissermaáen Forth neu gestartet.
Eine „hnliche Wirkung haben die Worte
ABORT und QUIT.
Im ultraFORTH83/volksFORTH83 gibt es Im ultraFORTH83/volksFORTH83 gibt es ein Wort ERROR", das sich von
ein Wort ERROR", das sich von ABORT" nur ABORT" nur dadurch unterscheidet, daß der Datenstack nicht gelöscht
dadurch unterscheidet, daá der wird. Desweiteren enthält dieses Forth eine User-Variable
Datenstack nicht gel”scht wird. ERRORHANDLER, die es ermöglicht, ein anderes Verhalten von ABORT" und
Desweiteren enth„lt dieses Forth eine ERROR" zu installieren.
User-Variable ERRORHANDLER, die es
erm”glicht, ein anderes Verhalten von
ABORT" und ERROR" zu installieren.
* Was soll eine Fehlerbehandlung können
o Was soll eine Fehlerbehandlung Diese Art der Fehlerbehandlung funktioniert zwar meistens recht gut,
k”nnen wirft aber einige Probleme auf. Im folgenden wird versucht, folgende
Diese Art der
Fehlerbehandlung
funktioniert zwar meistens recht gut,
wirft aber einige Probleme auf.
Im folgenden wird versucht, folgende
Stichworte zu diskutieren: Stichworte zu diskutieren:
- Reservierte Ressourcen - Reservierte Ressourcen schließen
schlieáen - Das Level, auf dem die Behandlung erfolgt
- Das Level, auf dem die Behandlung - Informationen über den Fehlerzustand erhalten.
erfolgt - Übersichtliche Behandlung selten auftretender Ereignisse
- Informationen <20>ber den - Fehler auch während der Fehlerbehandlung (ohne Endlosschleifen)
Fehlerzustand erhalten.
- šbersichtliche Behandlung
selten auftretender Ereignisse
- Fehler auch w„hrend der
Fehlerbehandlung (ohne
Endlosschleifen)
Hierbei flieáen jeweils die Erfahrungen Hierbei fließen jeweils die Erfahrungen des Autors mit MS-DOS, Pascal,
des Autors mit MS-DOS, Pascal,
Modula-2, Fortran und TLC-Lisp mit ein. Modula-2, Fortran und TLC-Lisp mit ein.
o Schlieáen von Ressourcen * Schließen von Ressourcen
Das Wort ABORT" (so es im Quelltext Das Wort ABORT" (so es im Quelltext vorliegt) zeigt bereits daß im
vorliegt) zeigt bereits daá im Fehlerfalle gewisse Systemressourcen wieder freigegeben werden müssen.
Fehlerfalle gewisse Systemressourcen Zumindest dürfte in jedem System der Return-stack entleert werden, oft
wieder freigegeben werden m<>ssen. auch der Datenstack, vielleicht werden sogar gewisse Systemvektoren
Zumindest d<>rfte in jedem System der restauriert (insb. für die Standard-Ein/Ausgabe scheint das geraten).
Return-stack entleert werden, oft auch Falls das Programm gewisse weitere Ressourcen reserviert hat, werden
der Datenstack, vielleicht werden sie nicht wieder frei gegeben. Dies könnte ein geöffnetes File sein,
sogar gewisse Systemvektoren restauriert das nicht geschlossen wird; ein Semaphor, das gelockt bleibt; ein
(insb. f<>r die Standard-Ein/Ausgabe menüartiger Bildschirm, der weiter in allen Farben des Spektrums
scheint das geraten). blinkt; eine hoffnungslos verdrehte Schnittstelle etc.. Am
Falls das Programm gewisse auffälligsten ist eine z.B. auf den Drucker umgeleitete
weitere Ressourcen Standardausgabe, wenn sie von ABORT" nicht restauriert wird.
reserviert hat, werden sie nicht wieder
frei gegeben. Dies k”nnte ein ge”ffnetes
File sein, das nicht geschlossen wird;
ein Semaphor, das gelockt bleibt; ein
men<EFBFBD>artiger Bildschirm, der weiter in
allen Farben des Spektrums blinkt; eine
hoffnungslos verdrehte Schnittstelle
etc.. Am auff„lligsten ist eine z.B. auf
den Drucker umgeleitete Standardausgabe,
wenn sie von ABORT" nicht restauriert
wird.
In diesem Fall wird schon die Ausgabe
der ABORT"-Meldung (auf den Drucker)
fehlschlagen, insb. wenn die gew<65>nschte
Fehlermeldung "Drucker ausgeschaltet"
heiáen mag. Dieser Effekt wird in jedem
intelligenten Forth-System nat<61>rlich
abgefangen, unter MS-DOS l„át er
sich allerdings noch sehr h<>bsch
beobachten. Die gelockten Semaphore
machen sich allerdings - in seltenen
F„llen - auch unter volksFORTH
bemerkbar. V”llig hoffnungslos wird der
Fall, wenn eine grӇere
Stand-Alone-Anwendung (z.B. ein
f<EFBFBD>rchterlich kompliziertes Men<65>programm)
grade s„mtliche Systemvektoren
erfolgreich verbogen hat und nun durch
einem j„mmerlich kleinen Fehler
(vielleicht einen offengelassener
Diskettenschacht) j„h in die
Forth-Hauptschleife geschleudert wird.
o Auf welcher Programmebene soll der In diesem Fall wird schon die Ausgabe der ABORT"-Meldung (auf den
Fehler behandelt werden? Drucker) fehlschlagen, insb. wenn die gewünschte Fehlermeldung
"Drucker ausgeschaltet" heißen mag. Dieser Effekt wird in jedem
intelligenten Forth-System natürlich abgefangen, unter MS-DOS läßt er
sich allerdings noch sehr hübsch beobachten. Die gelockten Semaphore
machen sich allerdings - in seltenen Fällen - auch unter volksFORTH
bemerkbar. Völlig hoffnungslos wird der Fall, wenn eine größere
Stand-Alone-Anwendung (z.B. ein fürchterlich kompliziertes
Menüprogramm) grade sämtliche Systemvektoren erfolgreich verbogen hat
und nun durch einem jämmerlich kleinen Fehler (vielleicht einen
offengelassener Diskettenschacht) jäh in die Forth-Hauptschleife
geschleudert wird.
In einem Fall * Auf welcher Programmebene soll der Fehler behandelt werden?
wie letzterem w„re es sogar denkbar,
den Fehler noch innerhalb der In einem Fall wie letzterem wäre es sogar denkbar, den Fehler noch
Systemroutinem (in diesem Fall in der innerhalb der Systemroutinem (in diesem Fall in der Block-Lese-Routine
Block-Lese-Routine des Betriebssystem) des Betriebssystem) zu beseitigen (z.B. den Benutzer aufzufordern,
zu beseitigen doch bitte den Schacht zu schließen) und anschließend fortzufahren,
(z.B. den Benutzer aufzufordern, doch ohne daß das darüberliegende Programm etwas bemerkt. Derartiges kann
bitte den Schacht zu schlieáen) und sogar MS-DOS. Alle Fehler die in Zusammenhang mit Diskettenlaufwerkern
anschlieáend fortzufahren, ohne daá stehen werden noch innerhalb des Betriebssystems mit einer Meldung der
das dar<61>berliegende Programm etwas
bemerkt. Derartiges kann sogar MS-DOS.
Alle Fehler die
in Zusammenhang mit Diskettenlaufwerkern
stehen werden noch innerhalb des
Betriebssystems mit einer Meldung der
Form: Form:
allgemeiner Fehler. Kaffee in Laufwerk A: allgemeiner Fehler. Kaffee in Laufwerk A:
(A)bbruch, (W)iederholen, (I)gnorieren ? (A)bbruch, (W)iederholen, (I)gnorieren ?
beantwortet. Der Benutzer kann sich nun beantwortet. Der Benutzer kann sich nun für eine der Alternativen
f<EFBFBD>r eine der Alternativen entscheiden. entscheiden. Tippt er 'W', so versucht das System denselben Zugriff
Tippt er 'W', so versucht das System nochmal. Dies ist bei einem offen gelassenen Schacht nützlich, gegen
denselben Zugriff nochmal. Dies ist bei Kaffee hilft es natürlich nicht. 'A' terminiert das laufende Programm
einem offen gelassenen Schacht n<>tzlich, und springt zurück ins Betriebssystem (in etwa wie unser QUIT). Dies
gegen Kaffee hilft es nat<61>rlich nicht. funktioniert meistens, es sei denn das Betriebssystem möchte selbst
'A' terminiert das laufende Programm und Teile seiner selbst von der Diskette lesen: Wir bekommen die beliebte
springt zur<75>ck ins Betriebssystem (in Endlosschleife, bis wir eine saubere Diskette eingelegt haben. Die
etwa wie unser QUIT). Dies funktioniert Alternative 'I' ist die hübscheste. Das System vergißt die Operation
meistens, es sei denn das Betriebssystem und kehrt ins rufende Programm zurück. Dieses arbeitet brav weiter,
m”chte selbst Teile seiner selbst von bis es sich an irgendwelchenden Zufallsergebnissen den Magen verdirbt.
der Diskette lesen: Wir bekommen die Um zum Beispiel des Menü-Programms mit offenen Kassettenschacht noch
beliebte Endlosschleife, bis wir eine ein Wort zu verlieren: Beim 'W'iederholen ist natürlich trotz allem
saubere Diskette eingelegt haben. der Bildschirmaufbau im Eimer. Bis hierher läßt sich erstmal
Die Alternative 'I' ist die h<>bscheste. formulieren, daß die Fehlerbehandlung lieber auf der Ebene des
Das System vergiát die Operation und Anwenderprogramms erfolgen sollte.
kehrt ins rufende Programm zur<75>ck.
Dieses arbeitet brav weiter, bis es
sich an irgendwelchenden Zufallsergebnissen
den Magen verdirbt. Um zum Beispiel
des Men<65>-Programms mit offenen
Kassettenschacht noch ein Wort zu
verlieren: Beim 'W'iederholen ist
nat<EFBFBD>rlich trotz allem der
Bildschirmaufbau im Eimer. Bis hierher
l„át sich erstmal formulieren, daá
die Fehlerbehandlung lieber auf der
Ebene des Anwenderprogramms erfolgen
sollte.
o Warum eigentlich nur Fehler mit * Warum eigentlich nur Fehler mit Methoden der Fehlerbehandlung behandeln?
Methoden der Fehlerbehandlung
behandeln?
Um diesem h<>bschen Wortspiel Sinn zu Um diesem hübschen Wortspiel Sinn zu geben, mag ein anderes Beispiel
geben, mag ein anderes Beispiel herhalten. Ein Programm lese Daten von einem File, verarbeite sie und
herhalten. schreibe das Ergebnis auf ein anderes File. Es muß somit (wenn es
Ein Programm lese strukturiert sein möchte) vor dem Lesen jedes einzelnen Zeichens das
Daten von einem File, verarbeite sie und Betriebssystem befragen, ob das File vielleicht schon erschöpft ist.
schreibe das Ergebnis auf ein anderes Das ergibt beispielsweise in Pascal endlose Konstrukte des
File. Strickmusters:
Es muá somit (wenn es strukturiert sein
m”chte) vor dem Lesen jedes einzelnen
Zeichens das Betriebssystem befragen, ob
das File vielleicht schon ersch”pft ist.
Das ergibt beispielsweise in Pascal
endlose Konstrukte des Strickmusters:
WHILE not eof(input) DO WHILE not eof(input) DO
WHILE not eoLn(input) DO WHILE not eoLn(input) DO
@ -223,29 +138,20 @@ endlose Konstrukte des Strickmusters:
ENDIF; ENDIF;
END; END;
Man verzeihe es mir, wenn ich die Man verzeihe es mir, wenn ich die Pascal-Syntax nicht mehr so
Pascal-Syntax nicht mehr so besonders besonders gut kann. Das Strickmuster sollte eigentlich etwas anderes
gut kann. Das Strickmuster sollte zeigen: In Pascal erfordert jeder Zugriff eines Programms (so es sich
eigentlich etwas anderes zeigen: In strukturiert nenn will) das Abfragen auf End-Of-File und End-Of-Line.
Pascal erfordert jeder Zugriff eines Letzteres ist nötig, da der Standard leider (?) nicht vorschreibt, wie
Programms (so es sich strukturiert nenn EOLn am Fileende aussieht. Soll innerhalb der großen WHILE-Schleife
will) das Abfragen auf End-Of-File und ein weiteres Zeichen gelesen werden, so muß beides erneut geprüft
End-Of-Line. Letzteres ist n”tig, da der werden, daß System ärgert sich mit ständigem Abgefrage herum, der
Standard leider (?) nicht vorschreibt, Programmierer mit der Definition der Routine 'schweinkram', die ihren
wie EOLn am Fileende aussieht. Soll Namen i.a. zu Recht trägt.
innerhalb der groáen WHILE-Schleife ein
weiteres Zeichen gelesen werden, so muá
beides erneut gepr<70>ft werden, daá System
„rgert sich mit st„ndigem Abgefrage
herum, der Programmierer mit der
Definition der Routine 'schweinkram',
die ihren Namen i.a. zu Recht tr„gt.
Viel einfacher haben es da Sprachen, die Viel einfacher haben es da Sprachen, die keinerlei Anspruch auf
keinerlei Anspruch auf strukturiertes strukturiertes Programmieren erheben. Das obige Kuddelmuddel ließe
Programmieren erheben. Das obige sich in Fortran etwa so umgehen:
Kuddelmuddel lieáe sich in Fortran etwa
so umgehen:
10 READ (input,char,end=100,err=200) 10 READ (input,char,end=100,err=200)
IF char.eq..... THEN IF char.eq..... THEN
@ -256,60 +162,36 @@ so umgehen:
100 ...<fileEnde behandeln>... 100 ...<fileEnde behandeln>...
200 ...<sonstige Fehler behandeln>... 200 ...<sonstige Fehler behandeln>...
Die 'end=' und 'err=' Sequenzen sind Die 'end=' und 'err=' Sequenzen sind verkappte GOTOs. Hier wird
verkappte GOTOs. (völlig unstrukturiert) der Programmfluß im Fehlerfall unterbrochen
Hier wird (v”llig unstrukturiert) der und an den durch 100 und 200 gekennzeichneten Stellen fortgesetzt. Ein
Programmfluá im Fehlerfall unterbrochen ähnliches GOTO-Konstrukt bietet auch Pascal an. Jedes gute Lehrbuch
und an den durch 100 und 200 bittet aber darum es möglichst nie zu benutzen. Als einzigen
gekennzeichneten Stellen fortgesetzt. tolerierbaren Zweck wird meist die Fehlerbehandlung angegeben. Ein
Ein „hnliches GOTO-Konstrukt bietet auch sehr treffender Beleg dafür, daß grade dem Vater der strukturierten
Pascal an. Jedes gute Lehrbuch bittet Programmierung, Herrn Wirth, die Fehlerbehandlung Kopfzerbrechen
aber darum es m”glichst nie zu benutzen.
Als einzigen tolerierbaren Zweck wird
meist die Fehlerbehandlung angegeben.
Ein sehr treffender Beleg daf<61>r, daá
grade dem Vater der strukturierten
Programmierung, Herrn Wirth, die
Fehlerbehandlung Kopfzerbrechen
bereitet. bereitet.
Was sollte das nun belegen? Es soll Was sollte das nun belegen? Es soll zeigen, daß erstens auch völlig
zeigen, daá erstens auch v”llig normale Vorgänge (Ende eines Files) fehlerbehandelt werden wollen. In
normale Vorg„nge (Ende eines Files) diesem Fall spricht man von 'Ausnahmebehandlung', da dieser
fehlerbehandelt werden wollen. In diesem Programmierstil nur für selten auftretende Fälle sinnvoll ist. Es soll
Fall spricht man von zweitens zeigen, daß eine Erhöhung der Performance und Wartbarkeit aus
'Ausnahmebehandlung', da dieser sinnvoller Ausnahmebehandlung entspringt. Denn sicher spart das obige
Programmierstil nur f<>r selten Fortran-beispiel einigen Code. Dies spart auch Zeit, da an weniger
auftretende F„lle sinnvoll ist. Es soll Stellen auf Fehler geprüft werden muß. Und ich kann es besser lesen.
zweitens zeigen, daá eine Erh”hung der (Zur Frage der Lesbarkeit steht mir als Nicht-Informatiker kein
Performance und Wartbarkeit aus allgemeines Urteil zu. Die 'ich'-Form spart mir hier sicher wieder
sinnvoller Ausnahmebehandlung
entspringt. Denn sicher spart das obige
Fortran-beispiel einigen Code. Dies
spart auch Zeit, da an weniger
Stellen auf Fehler gepr<70>ft
werden muá. Und ich kann es besser
lesen. (Zur Frage der Lesbarkeit steht
mir als Nicht-Informatiker kein
allgemeines Urteil zu. Die
'ich'-Form spart mir hier sicher wieder
einigen Streit mit Helge und Gerd.) einigen Streit mit Helge und Gerd.)
o Ist Ausnahmebehandlung * Ist Ausnahmebehandlung auf ganz tiefer Ebene verzichtbar ?
auf ganz tiefer Ebene verzichtbar ?
Manchmal muá aber auch eine Manchmal muß aber auch eine Ausnahmebehandlung auf ganz tiefer Ebene
Ausnahmebehandlung auf ganz tiefer erfolgen. Als Beispiel sei hier die Ausgabe von Informationen im
Ebene erfolgen. Als Beispiel sei hier Fehlerfall genannt. Häufig möchte der Benutzer im Fehlerfall wissen,
die Ausgabe von Informationen im wo der Fehler aufgetreten ist, wie bestimmte Variablen aussahen, etc.
Fehlerfall genannt. H„ufig m”chte der Im volksFORTH gibt es ein Wort UNRAVEL, das die Aufrufhierarchie
Benutzer im Fehlerfall wissen, wo der ausgibt. Dies könnte etwa so aussehen:
Fehler aufgetreten ist, wie bestimmte
Variablen aussahen, etc.
Im volksFORTH gibt es ein Wort
UNRAVEL, das die Aufrufhierarchie
ausgibt.
Dies k”nnte etwa so aussehen:
FEHLER divide by Zero AUFGETRETEN. FEHLER divide by Zero AUFGETRETEN.
Der Fehler geschah in Wort: 0/ Der Fehler geschah in Wort: 0/
@ -318,82 +200,54 @@ FEHLER divide by Zero AUFGETRETEN.
aufgerufen von: EDIT aufgerufen von: EDIT
aufgerufen von: L aufgerufen von: L
Derartige POST-MORTEM-DUMPS erm”glichen Derartige POST-MORTEM-DUMPS ermöglichen i.a. ein schnelles
i.a. ein schnelles Lokalisieren des Lokalisieren des Fehlers. Sie enthalten des öfteren nicht nur die
Fehlers. Sie enthalten des ”fteren nicht Aufrufhierarchie sondern diverse Register- und Variablen-Inhalte zum
nur die Aufrufhierarchie sondern Zeitpunkt des Fehlers (am besten noch aus allen Unterprogrammen...),
diverse Register- und Variablen-Inhalte sodaß sie manchmal den Benutzer eher in hunderten von Seiten Papier
zum Zeitpunkt des Fehlers (am besten ersticken, als ihm bei der Fehlersuche zu helfen. Aber selbst dagegen
noch aus allen Unterprogrammen...), sind Kräuter gewachsen. Logitech's Modula-2-Compiler teilt dem
sodaá sie manchmal den Benutzer eher in Benutzer außer einer sehr knappen Fehlerbeschreibung nichts mit und
hunderten von Seiten Papier ersticken, schreibt ersatzweise den kompletten Systemzustand auf Diskette, wo man
als ihm bei der Fehlersuche zu helfen. ihn anschließend mit einem Post-Mortem-Debug-Programm umgraben kann.
Aber selbst dagegen sind Kr„uter Es frage mich bitte niemand, was passiert, wenn die Diskette voll war.
gewachsen. Logitech's Modula-2-Compiler Ruft der Fehler dann einen erneuten Post-Mortem-Dump hervor?
teilt dem Benutzer auáer einer sehr
knappen Fehlerbeschreibung nichts mit
und schreibt ersatzweise den kompletten
Systemzustand auf Diskette, wo man ihn
anschlieáend mit einem
Post-Mortem-Debug-Programm umgraben
kann. Es frage mich bitte niemand, was
passiert, wenn die Diskette voll war.
Ruft der Fehler dann einen erneuten
Post-Mortem-Dump hervor?
Um wieder zum Faden zur<75>ckzukehren: Um wieder zum Faden zurückzukehren: Zumindest zum Post-Mortem-Debuggen
Zumindest zum Post-Mortem-Debuggen (=Entlausen aus einem toten Programm. Übertragen: Infos über den
(=Entlausen aus einem toten Fehlerzustand erhalten) ist es nötig Fehler auf niedrigster Ebene zu
Programm. šbertragen: Infos behandeln.
<EFBFBD>ber den Fehlerzustand erhalten)
ist es n”tig Fehler auf niedrigster
Ebene zu behandeln.
o Mein Wunsch zur Fehlerbehandlung: * Mein Wunsch zur Fehlerbehandlung: Call-with-current-Continuation (CallCC)
Call-with-current-Continuation
(CallCC)
Die sch”nste, allgemeinste Art der Die schönste, allgemeinste Art der Fehlerbehandlung, die ich kenne,
Fehlerbehandlung, die ich kenne, ist das ist das CATCH-THROW-Konstrukt aus TLC-Lisp (von T.Allen). Ich habe mir
CATCH-THROW-Konstrukt aus TLC-Lisp (von sagen lassen, daß sie unter Zuhilfenahme des
T.Allen). Call-with-current-Continuation-Konzepts implementiert ist. Daher
Ich habe mir sagen lassen, daá sie unter gefällt mir dieses auch sehr gut. Da ich CallCC leider nicht kenne
Zuhilfenahme des beschränke ich mich jetzt aber wieder auf CATCH-THROW. Es wird in
Call-with-current-Continuation-Konzepts folgender Form benutzt:
implementiert ist. Daher gef„llt mir
dieses auch sehr gut. Da ich CallCC
leider nicht kenne beschr„nke ich mich
jetzt aber wieder auf CATCH-THROW.
Es wird in folgender Form benutzt:
(CATCH name ((expression) (CATCH name ((expression)
(exceptionhandler))) (exceptionhandler)))
Die Bedeutung ist folgende: Wenn w„hrend Die Bedeutung ist folgende: Wenn während der Evaluierung (=Ausführung
der Evaluierung (=Ausf<73>hrung auf auf LISPisch) von EXPRESSION eine Ausnahme mit dem Namen NAME
LISPisch) von EXPRESSION eine Ausnahme auftreten sollte, so möge bitte sofort EXCEPTIONHANDLER evaluiert
mit dem Namen NAME auftreten sollte, so werden. Ansonsten ist der obige Ausdruck identisch mit:
m”ge bitte sofort EXCEPTIONHANDLER
evaluiert werden. Ansonsten ist der
obige Ausdruck identisch mit:
(expression) (expression)
Eine Ausnahme tritt dadurch auf, daá Eine Ausnahme tritt dadurch auf, daß eine Funktion (=wort auf
eine Funktion (=wort auf LISPisch) innerhalb von expression die Funktion
LISPisch) innerhalb
von expression die Funktion
(THROW name) (THROW name)
aufruft. aufruft.
Eigentlich ist es verabscheuungsw<73>rdig, Eigentlich ist es verabscheuungswürdig, von Lisp aus Files zu lesen,
von Lisp aus Files zu lesen, da dies dem da dies dem funktionalen Programmieren zuwiderläuft. Um aber trotzdem
funktionalen Programmieren zuwiderl„uft. das obige File-Lese-Beispiel nochmal zu strapazieren:
Um aber trotzdem das obige
File-Lese-Beispiel nochmal zu
strapazieren:
(CATCH end-of-file (CATCH end-of-file
(CATCH end-of-line (CATCH end-of-line
@ -410,167 +264,114 @@ strapazieren:
( ...end-of-file-handler..) ( ...end-of-file-handler..)
) )
Dies sieht nicht nur wundervoll aus mit Dies sieht nicht nur wundervoll aus mit den vielen Klammern, sondern
den vielen Klammern, sondern hat auch hat auch eine Wirkung: wenn READCHAR irgendwann (THROW end-of-line)
eine Wirkung: wenn READCHAR irgendwann oder (THROW end-of-file) evaluiert, wird einer unsrer HANDLER
(THROW end-of-line) oder (THROW aufgerufen. Ob READCHAR das tut und ob es in Lisp überhaupt eine
end-of-file) evaluiert, wird einer Funktion diesen Namens gibt, entzieht sich leider meiner Kenntnis.
unsrer HANDLER aufgerufen. Ob READCHAR Selbstverständlich können solche handler geschachtelt werden. Um
das tut und ob es in Lisp <20>berhaupt eine DOSOMETHING könnte z.B. ein noch spezielleren handler heruminstalliert
Funktion diesen Namens gibt, entzieht werden. Eine Ausführung von (THROW name) aktiviert jeweils den
sich leider meiner Kenntnis. nächstäußeren (höhergelegenen) handler. Wenn dieser das nötige getan
Selbstverst„ndlich k”nnen solche handler hat, kann er beispielsweise erneut (THROW name) evaluieren, um
geschachtelt werden. Um DOSOMETHING wiederum den ihm nächstäußeren handler zu aktivieren. Das Spiel läßt
k”nnte z.B. ein noch sich weitertreiben, bis schließlich der alleräußerste (von der
spezielleren handler LISP-Interpreter-Schleife) installierte handler aufgerufen wird, der
heruminstalliert werden. Eine Ausf<73>hrung (ähnlich unserem ABORT") wieder Eingaben von der Tastatur verarbeitet.
von (THROW name) aktiviert jeweils den Selbstverständlich kann jeder handler in der Schlange auch etwas
n„chst„uáeren (h”hergelegenen) handler. anderes unternehmen, beispielsweise die gescheiterte Aktion
Wenn dieser das n”tige getan hat, kann
er beispielsweise erneut (THROW name)
evaluieren, um wiederum den ihm
n„chst„uáeren handler zu aktivieren. Das
Spiel l„át sich weitertreiben, bis
schlieálich der aller„uáerste (von der
LISP-Interpreter-Schleife) installierte
handler aufgerufen wird, der („hnlich
unserem ABORT") wieder Eingaben von der
Tastatur verarbeitet. Selbstverst„ndlich
kann jeder handler in der Schlange auch
etwas anderes unternehmen,
beispielsweise die gescheiterte Aktion
wiederholen. wiederholen.
o Zur<75>ck zu Forth * Zurück zu Forth
Aus dem gesagten seien noch einmal die Aus dem gesagten seien noch einmal die
Kernpunkte zusammengefaát: Kernpunkte zusammengefaßt:
- Fehlerbehandlung soll auf jeder
beliebigen Programmebene m”chlich sein - Fehlerbehandlung soll auf jeder beliebigen Programmebene möchlich
sein
- insbesondere auch auf tiefster Ebene - insbesondere auch auf tiefster Ebene
- Die Fehlerbehandlungsroutinen sollen - Die Fehlerbehandlungsroutinen sollen geschachtelt werden können
geschachtelt werden k”nnen - Fehlerbehandlar sollen Möglichkeiten erhalten, nach Bedarf die
- Fehlerbehandlar sollen M”glichkeiten fehlerverursachende Routine erneut zu probieren oder die Ausführung
erhalten, nach Bedarf die dem nächsthöheren Fehlerbehandler weiterzugeben.
fehlerverursachende Routine erneut zu - Das ganze soll so einfach zu benutzen sein, daß Routinen für selten
probieren oder die Ausf<73>hrung dem auftretende Ereignisse einfach zu formulieren sind.
n„chsth”heren - Diese Fehlerbehandlung soll durch das Standardwort ABORT" aktiviert
Fehlerbehandler weiterzugeben. werden.
- Das ganze soll so einfach zu benutzen
sein, daá Routinen f<>r selten
auftretende Ereignisse einfach zu
formulieren sind.
- Diese Fehlerbehandlung soll durch das
Standardwort ABORT" aktiviert werden.
Nun wird's konkret: Nun wird's konkret: Wo sollen die Informationen über die installierten
Wo sollen die Informationen <20>ber die Fehlerbehandlungsroutinen abgelegt werden? Auf dem Returnstack, da
installierten Fehlerbehandlungsroutinen sich hier am einfachsten eine der jeweiligen Ausführungsebene (Wort)
abgelegt werden? Auf dem Returnstack, da angelehnte Datenstruktur bilden läßt.
sich hier am einfachsten eine der
jeweiligen Ausf<73>hrungsebene (Wort)
angelehnte Datenstruktur bilden l„át.
Wie soll die Syntax aussehen? Es soll Wie soll die Syntax aussehen? Es soll einfach sein, daher
einfach sein, daher Kontrollstrukturen. Kontrollstrukturen. Beispielsweise:
Beispielsweise:
: name ..<clause1>.. : name ..<clause1>..
FAILS ...errorhandler... THEN FAILS ...errorhandler... THEN
..<clause2>.. ; ..<clause2>.. ;
Die Bedeutung: Es wird ein Wort NAME Die Bedeutung: Es wird ein Wort NAME definiert. Bei Ausführung führt
definiert. Bei Ausf<73>hrung f<>hrt NAME NAME erst <clause1> aus, installiert anschließend einen ERRORHANDLER,
erst <clause1> aus, installiert führt dann <clause2> aus und deinstalliert ERRORHANDLER nach Verlassen
anschlieáend einen ERRORHANDLER, f<>hrt des Wortes. Sollte innerhalb von <clause2> ein ABORT" ausgeführt
dann <clause2> aus und deinstalliert werden, so wird ERRORHANDLER ausgeführt.
ERRORHANDLER nach Verlassen des Wortes.
Sollte innerhalb von <clause2> ein
ABORT" ausgef<65>hrt werden, so wird
ERRORHANDLER ausgef<65>hrt.
Aktivieren des „uáeren ERRORHANDLERS: Aktivieren des äußeren ERRORHANDLERS: Sollte innerhalb von
Sollte innerhalb von ERRORHANDLER das ERRORHANDLER das Wort THROW ausgeführt werden, so wird die Ausführung
Wort THROW ausgef<65>hrt werden, so wird von ERRORHANDLER beendet und die nächstäußere Fehlerbehandlungsroutine
die Ausf<73>hrung von ERRORHANDLER beendet aktiviert.
und die n„chst„uáere
Fehlerbehandlungsroutine aktiviert.
Wiederholen der fehlerverursachenden Wiederholen der fehlerverursachenden <clause2>: Hier wird's kritisch.
<clause2>: Hier wird's kritisch. Im Im Gegensatz zu praktisch allen anderen Sprachen liegen die Parameter
Gegensatz zu praktisch allen anderen auf dem Datenstack. Vor einer Wiederholung müssen Daten- und
Sprachen liegen die Parameter auf dem Returnstack repariert werden. Der Returnstack läßt sich problemlos so
Datenstack. Vor einer Wiederholung manipulieren, daß er bei Aufruf von ERRORHANDLER bereits wieder im
m<EFBFBD>ssen Daten- und Returnstack repariert gewünschten Zustand ist. Falls ein definierter Zustand des Datenstacks
werden. Der Returnstack l„át sich gewümscht wird, muß allerdings ein spezielles Konstrukt:
problemlos so manipulieren, daá er bei
Aufruf von ERRORHANDLER bereits wieder
im gew<65>nschten Zustand ist. Falls ein
definierter Zustand des Datenstacks
gew<EFBFBD>mscht wird, muá allerdings ein
spezielles Konstrukt:
nn #FAILS ..errorhandler.. RETRY nn #FAILS ..errorhandler.. RETRY
benutzt werden. Die NN obersten benutzt werden. Die NN obersten Stackwerte, sowie der Stackpointer
Stackwerte, sowie der Stackpointer werden gesichert. Falls ERRORHANDLER aufgerufen werden sollte, wird
werden gesichert. Falls ERRORHANDLER der Stack vorher soweit restauriert. Es gilt natürlich aufzupassen,
aufgerufen werden sollte, wird der Stack daß sie bis zur Ausführung von RETRY auch dableiben.
vorher soweit restauriert. Es gilt
nat<EFBFBD>rlich aufzupassen, daá sie bis
zur Ausf<73>hrung von RETRY auch dableiben.
Noch ein weiteres Konstrukt wurde Noch ein weiteres Konstrukt wurde eingeführt:
eingef<EFBFBD>hrt:
: name ..<clause1>.. : name ..<clause1>..
EXITS ..errorhandler.. throw THEN EXITS ..errorhandler.. throw THEN
..<clause2>. ; ..<clause2>. ;
Es tr„gt der Idee Rechnung, daá Es trägt der Idee Rechnung, daß ERRORHANDLER des öfteren nur
ERRORHANDLER des ”fteren nur installiert installiert wird, um eine Ressource zu schließen. Die Bedeutung: Es
wird, um eine Ressource zu schlieáen. wird ein Wort NAME definiert. Bei Ausführung führt NAME erst <clause1>
Die Bedeutung: Es wird ein Wort NAME aus, installiert anschließend einen ERRORHANDLER, führt dann <clause2>
definiert. Bei Ausf<73>hrung f<>hrt NAME aus. ERRORHANDLER wird im Falle eines Fehlers oder nach Verlassen des
erst <clause1> aus, installiert Wortes NAME ausgeführt. Es lassen sich also so schöne Konstrukte
anschlieáend einen ERRORHANDLER, f<>hrt
dann <clause2> aus. ERRORHANDLER wird
im Falle eines Fehlers oder nach
Verlassen des Wortes NAME ausgef<65>hrt.
Es lassen sich also so sch”ne Konstrukte
bilden wie: bilden wie:
: machWas ... : machWas ...
..<”ffne-Ger„t1>.. ..<öffne-Gerät1>..
EXITS ..<schlieáe-Ger„t1>.. throw THEN EXITS ..<schließe-Gerät1>.. throw THEN
..<”ffne-Ger„t2>.. ..<öffne-Gerät2>..
EXITS ..<schlieáe-Ger„t2>.. throw THEN EXITS ..<schließe-Gerät2>.. throw THEN
.... ; .... ;
Es werden auf jeden Fall die ge”ffneten Es werden auf jeden Fall die geöffneten Geräte wieder geschlossen, ob
Ger„te wieder geschlossen, ob nun ein nun ein Fehler auftritt oder nicht.
Fehler auftritt oder nicht.
o Was gibt es noch f<>r Ans„tze in Forth * Was gibt es noch für Ansätze in Forth
Der vorgestellte Ansatz bringt nichts Der vorgestellte Ansatz bringt nichts prinzipiell neues. In
prinzipiell neues. In ///////Schliesieck ///////Schliesieck läßt sich eine Methode nachlesen, die sicherlich
l„át sich eine Methode nachlesen, die schneller und einfacher implementiert ist, allerdings verändert sie
sicherlich schneller und einfacher nicht das Verhalten von ABORT", sondern muß mit einem gesonderten Wort
implementiert ist, allerdings ver„ndert aufgerufen werden. Auch sichert sie lediglich den Stackpointer,
sie nicht das Verhalten von ABORT", eventuelle Parameter müssen also 'zu Fuß' gesichert werden.
sondern muá mit einem gesonderten Wort //////weiter.... wenn m
aufgerufen werden. Auch sichert sie
lediglich den Stackpointer, eventuelle
Parameter m<>ssen also 'zu Fuá'
gesichert werden. //////weiter....
wenn m
Sch”ner: statt THROW ein EXIT chöner: statt THROW ein EXIT nehmen. Was passiert bei exit? Bitte
nehmen. Was passiert bei exit? nicht IF..ELSE..RETRY Bitte kein FAILS...THEN ohne throw oder so
Bitte nicht IF..ELSE..RETRY
Bitte kein FAILS...THEN ohne throw oder
so
Wie rauskriegen, welcher Fehler passiert ist? Wie rauskriegen, welcher Fehler passiert ist?


0
6502/UltraForth/README.TXT Executable file → Normal file
View File