Modul Metasprache im Racket

8

Ich versuche in Racket eine Modul-Meta-Sprache mylang zu schreiben, die eine zweite Sprache akzeptiert, an die der modifizierte Körper übergeben wird, so dass:

%Vor%

entspricht:

%Vor%

wobei der typed/racket -Teil natürlich durch jede andere Modulsprache ersetzt werden kann.

Ich habe eine einfache Version versucht, die den Körper unverändert lässt. Es funktioniert in der Befehlszeile gut , gibt jedoch den folgenden Fehler bei der Ausführung in DrRacket:

%Vor%

Hier ist der ganze Code:

%Vor%

Anforderungen (d. h. Lösungen, die ich lieber vermeiden möchte):

  • Das Hinzufügen eines (require (only-in typed/racket)) im Modul mylang funktioniert, aber ich bin an einer allgemeinen Lösung interessiert, bei der mylang nicht über typed/racket at al wissen muss (dh wenn jemand ein neues hinzufügt) language foo , dann sollte mylang mit dem out of the box funktionieren).
  • Ich bin auch nicht an Tricks interessiert, die ein Submodul deklarieren und sofort require und re provide it, wie hier , weil dadurch der Pfad zum eigentlichen Modul geändert wird (zB main und test verlieren ihr spezielles Verhalten).

    Es ist auch langsamer zur Kompilierzeit, da Submodule besucht und / oder mehrfach instanziiert (dies kann sein gesehen durch das Schreiben von (begin-for-syntax (displayln 'here)) und hat eine spürbare Auswirkung auf große typed/racket -Programme.

  • Bonuspunkte, wenn die Pfeile in DrRacket für von der delegierten Sprache bereitgestellte Einfügungen funktionieren, z. Im obigen Beispiel haben Sie Pfeile von ann , + und Number bis typed/racket/base .

Georges Dupéron 16.06.2016, 19:29
quelle

1 Antwort

4

Eine Sache, die Sie tun können, was meiner Meinung nach Ihre Anforderungen nicht verletzt, ist es in ein Modul zu stecken, dieses Modul vollständig zu erweitern und dann auf #%plain-module-begin anzupassen, um eine Anforderung einzufügen.

%Vor%

Und wenn du den Körper irgendwie transformieren willst, könntest du das entweder vor oder nach der Erweiterung machen.

Der Mustervergleich zum Einfügen der zusätzlichen (#%require lng) ist erforderlich, da das Erweitern des Modulkörpers in einem Kontext, in dem lng verfügbar ist, nicht ausreicht. Wenn Sie den Code mod-body wieder aus dem Formular module entfernen, bedeutet dies, dass sich die Bindungen auf lng beziehen, aber lng zur Laufzeit nicht verfügbar ist. Deshalb bekomme ich den require: namespace mismatch; reference to a module that is not available -Fehler ohne ihn, und deshalb muss er nach der Erweiterung hinzugefügt werden.

Aktualisierung von Kommentaren

Wie Georges Dupéron in einem Kommentar darauf hingewiesen hat, führt dies jedoch zu einem weiteren Problem. Wenn lng einen Bezeichner x liefert und das Modul, in dem es verwendet wird, ein anderes x importiert, wird ein Importkonflikt auftreten, wo dies nicht sein sollte. Require-Zeilen sollten sich in einem "verschachtelten Bereich" in Bezug auf die Modulsprache befinden, damit sie Kennungen wie x hier schattieren können.

@ GeorgesDupéron hat in dieser E-Mail auf der Racketbenutzerliste , indem Sie (make-syntax-introducer) für mod-body verwenden, um den verschachtelten Bereich zu erstellen.

%Vor%     
Alex Knauth 25.06.2016, 19:15
quelle

Tags und Links