2016-07-31 26 views
1

Ich habe das folgende Skript, ~/tmp/2.tcl:Warum stoppt meine Ablaufverfolgung der TCL-Ausführung nicht bei den Kompilierfunktionen?

proc p1 {a} { 
    if {[expr $a + 10] > 100} { 
     puts hi 
    } 
} 

set a [p1 200] 

Ich habe eine Debug-build TCL v8.6.1, Ich mag zu verfolgen, was in TCL Ausführung vor sich geht, wenn ich „./tclsh8.6 ~/tmp/2.tcl“ ausgeben, so dass ich gdb die die Ausführung (in gdb, set args ~/tmp.2.tcl,) zu verfolgen

Was verwirrte ich bin:

1. In `TclEvalEx`(), it is command by command parsing and execution, I do not see any 
script/command compiling. 

2. I set breakpoints at `TclAttemptCompileProc(), TclCompileObj()` and `TclCompileExpr`(), 
they are not triggered. 

Was vermisse ich hier? Warum wird kein Skript kompiliert? Hier

ist der Backtrace des Laufens TclEvalEx:

#0 TclEvalEx (interp=0x613680, script=0x674950 "proc p1 {a} {\n if {[expr $a + 10] > 100} {\n  puts hi\n }\n}\n\nset a [p1 200]\n\n", numBytes=87, flags=0, line=1, clNextOuter=0x0, 
    outerScript=0x674950 "proc p1 {a} {\n if {[expr $a + 10] > 100} {\n  puts hi\n }\n}\n\nset a [p1 200]\n\n") at ~/tcl8.6.1/source/generic/tclBasic.c:4935 
#1 0x00007ffff7af0812 in Tcl_FSEvalFileEx (interp=0x613680, pathPtr=0x65beb0, encodingName=0x0) at ~/tcl8.6.1/source/generic/tclIOUtil.c:1809 
#2 0x00007ffff7afb88f in Tcl_MainEx (argc=-1, argv=0x7fffffffde08, appInitProc=0x400963 <Tcl_AppInit>, interp=0x613680) at ~/tcl8.6.1/source/generic/tclMain.c:417 
#3 0x000000000040095c in main (argc=2, argv=0x7fffffffddf8) at ~/tcl8.6.1/source/unix/tclAppInit.c:84 

[UPDATE] Ich bin nicht sicher, was schiefgeht, jetzt die Haltepunkte haben ausgelöst werden.

+0

in Klammern, das erste Argument zu 'if' (und' while' und der zweite arg zu 'for') wird bereits als' expr'ession ausgewertet, also 'if {$ a + 10> 100} ... 'ist ausreichend –

Antwort

1

Der Compiler hat einige interne Einspeisepunkten - es ist nicht in irgendeiner Weise eine öffentliche API und unterliegen Änderungen ohne jemand ankündigt es - und TclSetByteCodeFromAny und TclCompileScript erscheinen unter denjenigen sein, die Sie verpasst haben . Es gibt auch andere; es ist eigentlich peinlich, sie alle aufzulisten. Sie sollten wahrscheinlich stattdessen einen Haltepunkt auf TclInitCompileEnv setzen, die die interne Standardfunktion ist, die verwendet wird, um die Struktur einzurichten, die von dem Compiler verwandt wird; alles , dass es nennt, wird für Sie von Interesse sein.


FWIW, der Aufruf an proc nicht den Körper des Verfahrens kompilieren. Dies wird verschoben, bis der Code benötigt wird, d. H. Bis die Prozedur aufgerufen wird. Der Aufruf von , den Sie gesehen haben, wird nicht viel sinnvolle Kompilierung direkt machen. Auch die nicht-rekursive Ausführungsengine in Tcl 8.6. * Macht es viel schwieriger mit einem Tool wie GDB debuggen. Der C-Stapel spiegelt den Tcl-Stapel überhaupt nicht wider.

Viel Glück.

+0

Ich bin fasziniert von Ihrer Aussage, die nicht-rekursive Ausführung-Engine in Tcl 8.6. * macht es viel schwieriger zu debuggen mit einem Werkzeug wie gdb, können Sie auf diesen Punkt näher eingehen? –

+1

Es war einmal * der Fall, dass jeder Prozeduraufruf am Ende einige Stack-Frames auf den C-Stack setzen würde, und auch einige Tcl-Befehle. Gehe zurück zu Tcl 8 und es gab eine direkte Korrespondenz, und ein Debugger konnte genau sehen, was Tcl vorhatte; Das änderte sich ein wenig mit dem Bytecode-Compiler, aber Sie konnten es immer noch ziemlich gut herausfinden. Der NRE-Motor in 8.6 bläst das weg; Normalerweise haben Sie zwischen dem C-Stack und dem Tcl-Stack überhaupt keine Beziehung mehr. Wir hatten jemanden, der sich damit beschäftigte, die Debugability zu verbessern, aber er starb an Krebs. –