====== catch throw ====== Schritt für Schritt durch catch den throw. Hier zunächst die Begriffsklärung. ''sp@ ( -- addr )'' Zeiger auf den obersten Datenstackeintrag. ''rp@ ( -- addr )'' Zeiger auf den obersten Returnstackeintrag. ''sp! ( addr -- )'' Stellt den Datenstackzeiger auf addr ein. Damit wird die Tiefe des Datenstack auf den selben Wert eingestellt, der bestand unmittelbar bevor sp@ ausgeführt wurde. ''rp! ( addr -- )'' Stellt den Returnstackzeiger auf addr ein. Damit wird die Tiefe des Returnstack auf den selben Wert eingestellt, der bestand unmittelbar bevor sp@ ausgeführt wurde. Die Abkürzungen bedeuten: * #exc = (exeption number) Nummer der Ausnahme. * i*x = alle Werte auf dem Stack unterhalb von #exc * i*adr = alle Werte auf dem Returnstack oberhalb des letzten Rahmens für die Ausnahmen (catchframe). * xt = Ausführbares Zeichen (execution address) das im catch drinnen mittels EXECUTE ausgeführt wird. * RS: = Abbild des Returnstack ===== Schritt für Schritt durchs CATCH ===== variable handler \ Variable für den letzten Ausnahmefall. \ Leg den Ausnahmerahmen hier an. \ v v : CATCH ( xt -- exc# | 0 ) ( 1) ( 2) sp@ >r ( -- xt) ( RS: -- sp ) ( 3) handler @ >r ( -- xt) ( RS: -- sp hlr ) ( 4) rp@ handler ! ( -- xt) ( RS: -- sp hlr ) ( 5) execute ( -- ) ( RS: -- sp hlr ) ( 6) r> handler ! ( -- ) ( RS: -- sp ) ( 7) r> drop ( -- ) ( RS: -- ) ( 8) 0 ( -- 0 ) ( 9) ; - Erzeugt einen Rahmen damit das throw auf Ausnahmen reagieren kann. Gibt die gerade erzeugte Ausnahmenummer weiter. - Das Ausführungssysmbol XT liegt schon auf dem Stack. - Rettet den Datenstackzeiger; ohne das aktuelle xt. - Rettet den vorherigen Ausnahmefall. - Speichert den aktuellen Ausnahmefall. - Führe das Wort aus das auf dem Stack liegt. Es ist nun geschützt in deiner Ausnahmeregelung eingebettet, die du in dem Wort machst, das catch enthält. - Restauriere den alten Ausnahmefall. - Verwerfe den Datenstackzeiger. - Ziege an, das alles normal verlaufen ist, indem eine 0 auf den Datenstack gelegt wird. ===== Schritt für Schritt durchs THROW ===== \ TROW springt zum gesicherten Rahmen falls #exc <> 0 ist. : THROW ( i*x exc# -- i*x exc# | i*x exc# ) ( RS: -- sp hlr i*adr ) ( 1) dup 0= ( -- i*x exc# f ) ( RS: -- sp hlr i*adr ) ( 2) if drop exit then ( -- i*x ) ( RS: -- sp hlr i*adr ) ( 3) handler @ rp! ( -- i*x exc# ) ( RS: -- sp hlr ) ( 4) r> handler ! ( -- i*x exc# ) ( RS: -- sp ) ( 5) r> ( -- i*x exc# sp ) ( RS: -- ) ( 6) swap ( -- i*x sp exc# ) ( RS: -- ) ( 7) >r ( -- i*x sp ) ( RS: -- exc# ) ( 8) sp! ( -- xt ) ( RS: -- exc# ) ( 9) drop r> ( -- exc# ) ( RS: -- ) ( 10) ; - THROW erwartet die Ausnahmenummer auf dem Stack, gibt sie weiter oder lässt sie fallen, und sein Returnstack hat einen Ausnahmerahmen unter all den derzeitigen Returnadressen. - Flag holen. - Noop - die 0 wird nicht weitergegeben. - Zum sicheren Ausnahmerahmen gehen. - Den vorherigen Ausnahmerahmen wieder herstellen. - Den gesicherten Datenstackzieger holen. - Datenstackzeiger restaurieren. - ebenso - ebenso - Ausnahmenummer übermitteln. Bereit die Ausnahmeregelungen auszuführen, die hinter dem aufrufenden catch angelegt wurden. ===== Beispiel: ===== \ Ermögliche dem "spam" eine Ausnahmenummer weiter zu geben. : spam ( -- ) ... #exc THROW ; \ Schließe "spam" in eine Ausnahmeregelung ein. : spam-exc ( i*x -- ) ... ['] spam CATCH ( -- #exc ) dup 0= IF drop exit then \ = NOOP dup #exc = IF ... \ Bekannte Ausnahme handhaben. else ... throw \ unvorhergesehene Ausnahme weitergeben an das Forthsystem. then ; ===== Bildergeschichte ===== {{words:s5_catch_throw.zip| Catch und Throw als Bildergeschichte}} S5 Slide Show - downloaden, auspacken und dann die datei ''index.html'' mit dem browser starten. ( finis)