当我的项目从Tcl8.5.9/ITCL3.4迁移到Tcl8.6.6/ITCL4.0.5时,我遇到了$this变量不一致的问题,这取决于它的访问方式。下面是最小化的测试用例:
puts "Tcl version : $tcl_patchLevel"
puts "Itcl version : [package require Itcl]"
itcl::class Base {
public {
method base_process {script} {
uplevel $m_main main_process [list $script]
}
method set_main {main} {
set m_main $main
}
}
protected {
variable m_main
}
}
itcl::class Main {
inherit Base
public {
method main_process {script} {
uplevel $script
}
}
}
itcl::class Worker {
inherit Base
public {
method worker_process_direct {} {
puts "Direct query: this = $this"
}
method worker_process_inderect {} {
base_process {puts "Indirect query: this = $this"}
}
method worker_process_both {} {
puts "Direct query: this = $this"
base_process {puts "Indirect query: this = $this"}
}
}
}
Main main
Worker worker
worker set_main main
puts "\n==== worker_process_direct ===="
worker worker_process_direct
puts "\n==== worker_process_indirect ===="
worker worker_process_inderect
puts "\n==== worker_process_both ===="
worker worker_process_bothworker_process_direct和worker_process_both函数总是提供正确的结果。但是worker_process_inderect只有在旧版本的Tcl/Itcl上才能正常工作。对于Tcl8.6.6/ITCL4.0.5,$this变量奇怪地更改为Main类的实例,而不是Worker。
下面是上面两个版本的Tcl/Itcl的脚本输出。
Tcl version : 8.5.9
Itcl version : 3.4
==== worker_process_direct ====
Direct query: this = ::worker
==== worker_process_indirect ====
Indirect query: this = ::worker <<<<<<<<<<<< CORRECT
==== worker_process_both ====
Direct query: this = ::worker
Indirect query: this = ::workerTcl version : 8.6.6
Itcl version : 4.0.5
==== worker_process_direct ====
Direct query: this = ::worker
==== worker_process_indirect ====
Indirect query: this = ::main <<<<<<<<<< INCORRECT
==== worker_process_both ====
Direct query: this = ::worker
Indirect query: this = ::worker我是不是遗漏了什么,Tcl/Itcl中有一些我没有注意到的重大变化?
发布于 2017-05-04 16:59:01
这是非常奇怪的!我将您的脚本扩充为如下定义Main:
itcl::class Main {
inherit Base
public {
method main_process {script} {
uplevel $script
# Print what is actually going on!
puts >>[tcl::unsupported::disassemble script $script]<<
}
}
}使用8.5/3.4时,我得到以下输出:
Tcl version : 8.5.9
Itcl version : 3.4
==== worker_process_direct ====
Direct query: this = ::worker
==== worker_process_indirect ====
Indirect query: this = ::worker
>>ByteCode 0x0x7fedea044c10, refCt 1, epoch 3, interp 0x0x7fedea033010 (epoch 3)
Source "puts \"Indirect query: this = $this\""
Cmds 1, src 35, inst 12, litObjs 3, aux 0, stkDepth 3, code/src 0.00
Commands 1:
1: pc 0-10, src 0-34
Command 1: "puts \"Indirect query: this = $this\""
(0) push1 0 # "puts"
(2) push1 1 # "Indirect query: this = "
(4) push1 2 # "this"
(6) loadScalarStk
(7) concat1 2
(9) invokeStk1 2
(11) done
<<
==== worker_process_both ====
Direct query: this = ::worker
Indirect query: this = ::worker
>>ByteCode 0x0x7fedea044c10, refCt 1, epoch 3, interp 0x0x7fedea033010 (epoch 3)
Source "puts \"Indirect query: this = $this\""
Cmds 1, src 35, inst 12, litObjs 3, aux 0, stkDepth 3, code/src 0.00
Commands 1:
1: pc 0-10, src 0-34
Command 1: "puts \"Indirect query: this = $this\""
(0) push1 0 # "puts"
(2) push1 1 # "Indirect query: this = "
(4) push1 2 # "this"
(6) loadScalarStk
(7) concat1 2
(9) invokeStk1 2
(11) done
<<在8.6/4.0版本中,我得到的结果是:
Tcl version : 8.6.3
Itcl version : 4.0.2
==== worker_process_direct ====
Direct query: this = ::worker
==== worker_process_indirect ====
Indirect query: this = ::main
>>ByteCode 0x0x1009af010, refCt 1, epoch 136, interp 0x0x100829a10 (epoch 136)
Source "puts \"Indirect query: this = $this"...
Cmds 1, src 35, inst 12, litObjs 3, aux 0, stkDepth 3, code/src 0.00
Commands 1:
1: pc 0-10, src 0-34
Command 1: "puts \"Indirect query: this = $this"...
(0) push1 0 # "puts"
(2) push1 1 # "Indirect query: this = "
(4) push1 2 # "this"
(6) loadStk
(7) strcat 2
(9) invokeStk1 2
(11) done
<<
==== worker_process_both ====
Direct query: this = ::worker
Indirect query: this = ::worker
>>ByteCode 0x0x1009b0210, refCt 1, epoch 136, interp 0x0x100829a10 (epoch 136)
Source "puts \"Indirect query: this = $this"...
Cmds 1, src 35, inst 11, litObjs 2, aux 0, stkDepth 3, code/src 0.00
Commands 1:
1: pc 0-9, src 0-34
Command 1: "puts \"Indirect query: this = $this"...
(0) push1 0 # "puts"
(2) push1 1 # "Indirect query: this = "
(4) loadScalar1 %v0
(6) strcat 2
(8) invokeStk1 2
(10) done
<<因此,8.5在两种(间接)情况下都使用loadScalarStk指令读取变量,而8.6在这两种情况下使用loadStk和loadScalar1来加载变量。这非常奇怪;我不希望loadScalar1出现在脚本片段中(它需要一个局部变量表),但至少它选取了期望值,而loadStk只是选取了完全错误的值。我还尝试在两个地方使用完全相同的值-脚本保存在一个共享变量- but中,该变量产生相同的输出;它看起来像是在一个地方计算,但选择了错误的值(可能是变量解析器的问题?)而在另一种情况下,它选择了正确的值,但原因是错误的(因为LVT不应该在脚本片段中使用;这只适用于完整的过程/方法)。不管怎样,这都是个坏消息。
请在http://core.tcl-lang.org/tcl/tktnew上提交错误报告,因为这闻起来像是几种错误的行为混合在一起。
https://stackoverflow.com/questions/43768288
复制相似问题