Module.nesting innerhalb von instance_eval / exec oder module_eval / exec

8

Ich kam auf diese Frage, als ich versuchte, dies zu beantworten . Folgendes ist ein erwartetes Verhalten:

%Vor%

Aber das Folgende:

%Vor%

all return [] . Warum funktionieren diese nicht wie oben?

Zusätzliche Frage

Mu ist zu kurz, schlug einen interessanten Punkt vor. Wenn das richtig ist, dann wäre Module.nesting eine der Methoden und Variablen, die vom literalen Kontext abhängen, wie Method#source_location , __FILE__ . Ist dieses Verständnis korrekt? Wenn ja, kann jemand das Inventar dieser Methoden / Variablen bereitstellen, die vom wörtlichen Kontext abhängig sind? Ich denke, es wäre nützlich als Referenz.

    
sawa 14.06.2011, 00:16
quelle

1 Antwort

7

Warnung : Das ist ein bisschen lang. Ein bisschen eine Tour durch den Ruby-Quellcode scheint notwendig, da die Dokumentation ein wenig dünn ist. Fühlen Sie sich frei, zum Ende zu springen, wenn Sie sich nicht dafür interessieren, wie Wurst gemacht wird.

Der 1.9.2 Module.nesting ist in eval.c wie folgt implementiert:

%Vor%

Ich kenne die Ruby-Interna nicht gut, aber ich lese die while -Schleife wie folgt: Extrahiere aus der verknüpften Liste cref alle Knoten, die mit einer klassenähnlichen Sache verbunden sind, aber nicht von ihr kommen %Code%. Das eval -Bit wird nur hier gesetzt:

%Vor%

Ein bisschen mehr Greife und Lesen zeigt, dass NODE_FL_CREF_PUSHED_BY_EVAL am Ende durch instance_eval geht. Ich überlasse die Überprüfung von yield_under , instance_exec und module_eval als Übungen für den Leser. In jedem Fall scheint module_exec explizit aus der instance_eval -Liste ausgeschlossen zu sein; Dies ist jedoch eher eine Ablenkung als alles andere, es bedeutet nur, dass Sie etwas nicht sehen, was die evals erwähnt.

Nun ist die Frage "Was sind Module.nesting und NODE alles?".

Wenn Sie in rb_vm_cref() suchen, sehen Sie eine Reihe von NODE-Konstanten für die verschiedenen Ruby-Schlüsselwörter und Sprachstrukturen:

  • node.h
  • NODE_BLOCK
  • NODE_BREAK
  • NODE_CLASS
  • NODE_MODULE
  • ...

also würde ich vermuten, dass NODE_DSYM ein Knoten im Befehlsbaum ist. Das passt gut zu meinem

  

NODE scheint mehr über das Sprechen mit dem Parser zu sein

Vermutung im Kommentar. Aber wir werden trotzdem weitermachen.

Die Funktion Module.nesting ist nur ein Wrapper für rb_vm_cref , der ein Wrapper für vm_get_cref ist. Worum geht es in vm_get_cref0 ? Es geht darum:

%Vor%

Alle drei Argumente für die Funktion stammen direkt aus diesem Steuerrahmen:

%Vor%

Die vm_get_cref0 scheint eine Befehlssequenz zu sein und die iseq und lfp sind Rahmenzeiger:

%Vor%

Die Definition von dfp ist relevant:

%Vor%

Es sieht also so aus, als ob Sie aus cref_stack eine Art Aufruf- oder Schachtelungsstapel bekommen.

Nun zurück zu den Einzelheiten. Wenn Sie dies tun:

%Vor%

Sie haben rb_vm_cref in der verknüpften Liste module A (die gefiltert wird, um das Array cref result zu erzeugen), da Sie noch nicht Module.nesting getroffen haben. Wenn Sie diese sagen:

%Vor%

Sie werden end in module A nicht mehr haben, weil Sie bereits cref popped end vom Stapel entfernt haben. Wenn Sie dies jedoch tun:

%Vor%

Sie sehen diese Ausgabe:

%Vor%

, weil die module A noch nicht geschlossen (und von module A entfernt) wurde.

Zum Schluss sagt die cref -Dokumentation Folgendes:

  

Gibt die Liste der verschachtelten Module zurück.

Ich denke, diese Aussage zusammen mit der Überprüfung der Interna zeigt an, dass Module.nesting tatsächlich von dem spezifischen wörtlichen Zusammenhang abhängt, in dem es aufgerufen wird.

Wenn jemand mit mehr Erfahrung im Ruby-Internal etwas hinzuzufügen hat, kann ich dies der SO-Community als Community-Wiki übergeben.

UPDATE : Dies gilt sowohl für Module.nesting als auch für class_eval und gilt auch für 1.9.3 genauso wie für 1.9.2.

>     
mu is too short 14.06.2011, 04:19
quelle

Tags und Links