2

Wie kann die try/catch/finally Funktionalität auf einem Interpreter implementiert werden (momentan bin ich auf F #)?Wie implementieren Try/Except/Endlich in einem erfundenen Sprachinterpreter mit goto oder ähnlichem?

Ich vermute, dass GOTOs verwendet werden können (ist aber auch notwendig, um die Funktionalität dafür im Interpreter zur Verfügung zu stellen, nicht viel Ahnung wie), aber ich habe GOTO nie in meinem Leben benutzt (nur wissen, ist böse!) und weder verstehen, wie die Umwelt erhalten.

P.D: Ich weiß bereits, dass CPS (Continuations) gemacht werden kann, um Ausnahmen und andere Kontrollflüsse zu emulieren. Jedoch komplizieren sie den Rest der Sprachimplementierung und verlangen Optimierungsdurchlauf, um den Aufwand dafür zu eliminieren, und für diese Frage möchte ich alternative Möglichkeiten zu verstehen, dass

PD2: Existieren Sie eine andere Alternative zu CPS, die zu einfach führen Implementierung von benutzerdefinierten Kontrollflüssen? Oder eine Möglichkeit, GOTOs dafür zu verallgemeinern?

+1

Eigentlich gibt es niemanden versuchen/außer/endlich. Es ist wirklich versuchen/außer und versuchen/schließlich und sie können innerhalb der anderen verschachtelt werden, z.B. (try (try Ausnahme) endlich). Dies macht es viel einfacher zu verarbeiten. –

+1

Ich bin mir nicht sicher, aber ich vermute, dass Sie Informationen zur Verwendung in [Typen und Programmiersprachen] (https://www.cis.upenn.edu/~bcpierce/tapl/) finden können, die den Code in F # umgerechnet hat. https://github.com/jackfoxy/fsharp-tapl](https://github.com/jackfoxy/fsharp-tapl) oder [Eine Einführung in die funktionale Programmierung durch Lambda-Kalkül] (https: //www.cs.rochester .edu/~ brown/173/Lesungen/LCBook.pdf) in Abschnitt 5.4 Fehler. –

Antwort

2

Control kann entkommen eine "versuchen" Block viele Möglichkeiten:

  • Goto ein Etikett in einem umgebenden Block (Anmerkung: goto X und gehe zu Y 2 verschiedene Fluchten)
  • Rückkehr aus der Funktion enthält die versuchen
  • Werfen eine Ausnahme im try
  • Propagieren eine Ausnahme von einer Funktion durch den Versuch Körper genannt
  • (detektierbar) -Aufruf exit() im try Körper

Sie könnten mehr haben, abhängig von Ihrer Sprache.

Was Ihr try-finally-Block tun muss, ist, all diese zu erfassen, den finally-Teil auszuführen und dann die beabsichtigte Aktion fortzusetzen.

Eine Möglichkeit, dies zu erreichen, ist die Erstellung einer Transferinsel für jeden Block Escape. Die Übertragungsinsel dient als Ziel für jede dieser Aktionen; Wenn die Steuerung an der Übertragungsinsel K ankommt, ist Block-Escape-K aufgetreten. Was die Transfer Insel tut, ist eine (parameterlos) Unterprogramm aufrufen, die die finally-Klausel enthält, und führt dann eine Aktion Flucht K.

Stellen Sie sich folgende try-finally-Block fortzusetzen:

try 
     ...goto X... // ... means some control structure wrapped around this 
     ...raise Z... 
     ...call q()... // throws exception 
     ...goto Y... 
     ...return 5... 
    finally 
     <some actions> 
    end 
    ...return <exp> 

Dieser Code könnte kompiliert werden als:

Mit diesem Hintergrund müssen Sie den Interpreter veranlassen, Aktionen auszuführen, als ob dieser Code vorhanden wäre. Offensichtlich muss der Interpreter die Transferinseln nicht instanziieren; Es kennt welche Art von Block Escape aufgetreten ist, kann die endgültige Aktion ausführen, und dann führen Sie die Block Escape weiter.