Verwenden von TemplateHaskell zum Auflisten aller Namen in einem Namespace

72

Ich möchte eine TemplateHaskell-Funktion variablesInScope :: Q [Name], die eine Liste Namealler Variablen im Gültigkeitsbereich zurückgibt . TemplateHaskell verfügt offensichtlich über diese Informationen, um Funktionen wie reify :: Name -> Q Infound zu implementieren lookupValueName :: String -> Q (Maybe Name).

Existiert die gewünschte Funktion irgendwo und ich habe sie einfach übersehen? Oder kann es einfach irgendwie gebaut werden?

Mike Izbicki
quelle
2
Ich bin mir ziemlich sicher, dass Sie dies nicht nur mit TH tun können, aber Sie können haskell-src-metaein Haskell-Modul als TH AST analysieren.
user2407038
1
Würde es erforderlich sein, die E / A-Funktionen der QMonade zu verwenden, um das Modul zu laden und diese dann an zu senden haskell-src-meta? Huch. Dies kann auch nicht eindeutig machen, welcher Name in dem bestimmten Bereich verwendet werden soll, in dem sich der Spleiß befindet.
Mike Izbicki
1
Ja, Sie müssen IO verwenden, um die Datei tatsächlich zu lesen. Ich bin mir nicht sicher, ob ich Ihre zweite Aussage verstehe - warum sollten Sie eindeutig sein, wenn Sie alle Namen erhalten? Sie könnten ein Ticket für eine Feature-Anfrage öffnen. Ich vermute, dass der zugrunde liegende Mechanismus, der TH antreibt, sowieso alle In-Scope-Namen zur Verfügung hat.
user2407038
1
Ich habe den Tickect ( # 9699 ) erstellt. Mit dem zweiten Punkt meine ich, dass eine Funktion möglicherweise eine aufgerufene Variable deklariert printund das printfrom System.IOdann nicht mehr im Gültigkeitsbereich liegt. Das Ergebnis von variablesInScopehat also eine ziemlich komplizierte Abhängigkeit davon, wo im Code der Spleiß auftritt.
Mike Izbicki

Antworten:

2

Leider kann man das nicht THalleine machen. Versuchen Sie haskell-src-meta, das Haskell-Modul als zu analysieren TH AST.

QZum Laden des Moduls sind jedoch die E / A-Funktionen der Monade erforderlich .

Bitte beziehen Sie sich auf https://ghc.haskell.org/trac/ghc/ticket/9699#ticket , um die aktuelle grobe Spezifikation zu sehen

(1) Erweitern Sie ModuleInfo (von reifyModule bezogen) auf ModuleInfo [Module] [Name], wobei [Module] weiterhin die Importliste ist und [Name] die Liste der exportierten Namen des Moduls enthält.

(2) Fügen Sie dieses Modul :: Q-Modul hinzu, das das aktuelle Modul erzeugt.

(3) Fügen Sie topLevelNames :: Q [Name] hinzu, um eine Liste der Namen der obersten Ebene (sowohl exportiert als auch nicht exportiert) zu erstellen, die im aktuellen Modul gebunden sind und für die Überprüfung sichtbar wären.

(4) Fügen Sie nestedNames :: Q [Name] hinzu (benötigt einen besseren Namen), um eine Liste der nicht verschachtelten (nicht verschachtelten) Namen zu erstellen, die in diesem Kontext zur Überprüfung sichtbar sind.

(5) Fügen Sie parentNames :: Q [Name] hinzu (auch wenn ein besserer Name erforderlich ist), um eine Liste der Namen zu erstellen, die unmittelbar mit dem aktuellen Spleißkontext verknüpft sind, sofern verfügbar. Zum Beispiel würde foo, bar :: $ (typeSplice) [foo, bar] sehen, foo = $ (exprSplice) würde [foo] sehen und $ (topLevelDecSplice) würde [] sehen.

(6) Optional Fügen Sie isTopLevel :: Name -> Q Bool hinzu, um festzustellen, ob ein Name auf der obersten Ebene (des aktuellen Moduls?) Gebunden ist. So etwas könnte alternativ durch Durchsuchen von topLevelNames erreicht werden.

Kirk Strobeck
quelle