在tcl中计算proc中的命令?

时间:2014-04-16 10:56:23

标签: windows tcl

有没有办法在执行前计算命令(可能是包含tclcmd的callstack号码)来自指定的proc名称?我认为需要假设源是可用的(不是为了预先推荐)。 感谢你。

1 个答案:

答案 0 :(得分:2)

动态分析

您可以使用跟踪来查找在执行特定过程期间执行的命令数。假设没有重新输入命令(即,不是递归的),你可以:

proc theProcedureOfInterest {} {
    # Whatever in here...
    for {set i 0} {$i < 5} {incr i} {
        puts i=$i
    }
}
trace add execution theProcedureOfInterest {enter leave enterstep} countCalls
proc countCalls {cmd args} {
    global counter
    switch [lindex $args end] {
        enter {
            set counter 0
        }
        enterstep {
            incr counter
            puts >>>$cmd
        }
        leave {
            puts "$counter calls in $cmd"
        }
    }
}

theProcedureOfInterest

如果执行上面的代码,则会得到以下输出:

>>>for {set i 0} {$i < 5} {incr i} {
        puts i=$i
    }
>>>set i 0
>>>puts i=0
i=0
>>>incr i
>>>puts i=1
i=1
>>>incr i
>>>puts i=2
i=2
>>>incr i
>>>puts i=3
i=3
>>>incr i
>>>puts i=4
i=4
>>>incr i
12 calls in theProcedureOfInterest

该代码里面有12个命令调用,你也可以自己计算。

这也将跟踪从该过程调用的过程(并使其处理递归调用是可能的,但更多涉及)。请注意,更改过程的定义将删除跟踪(如果需要,只需重新应用它),并注意这种跟踪会对性能产生重大影响(它极大地抑制了Tcl字节码编译器中可能的优化)。

静态分析

要获得代码的静态分析,您需要dkf-improved-disassembler branch(我还没有合并它)。然后,你可以这样做:

set disassembled [::tcl::unsupported::getbytecode script {
    # Whatever in here...
    for {set i 0} {$i < 5} {incr i} {
        puts i=$i
    }
}]
set commandCount [llength [dict get $disassembled commands]]

您还可以查看commands元素以查看已识别的命令(dict get [lindex [dict get $disassembled commands] $n] source)。它会检查像for之类的命令,但不会检查带有主体的自定义命令(因为它不理解它们是代码的一部分而不仅仅是一个有趣的字符串)。它也不知道它们被执行的频率;毕竟这是静态分析。