Itcl:$this变量的不一致性

Itcl:$this变量的不一致性,tcl,itcl,Tcl,Itcl,在将我的项目从Tcl 8.5.9/Itcl 3.4迁移到Tcl 8.6.6/Itcl 4.0.5的过程中,我遇到了$this变量的不一致性,这取决于它的访问方式。以下是最小化的测试用例: puts "Tcl version : $tcl_patchLevel" puts "Itcl version : [package require Itcl]" itcl::class Base { public { method base_process {script} {

在将我的项目从Tcl 8.5.9/Itcl 3.4迁移到Tcl 8.6.6/Itcl 4.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_both
worker\u process\u direct
worker\u process\u这两个功能始终提供正确的结果。但是,
worker\u process\inderect
只能在旧版本的Tcl/Itcl中正常工作。对于Tcl 8.6.6/Itcl 4.0.5
$这个
变量被奇怪地更改为
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 = ::worker
Tcl版本:8.5.9
Itcl版本:3.4
===工人\u进程\u直接====
直接查询:this=::worker
===工人\u过程\u间接====
间接查询:this=::worker现在这很奇怪!我扩充了您的脚本以定义
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]<<
        }
    }
}
itcl::class Main{
继承基础
公开的{
方法main_进程{script}{
uplevel$脚本
#打印实际发生的事情!
puts>[tcl::unsupported::反汇编脚本$script]>字节码0x0x7fedea044c10,参考文献1,历元3,内部0x7FEDEA033010(历元3)
Source“puts\”间接查询:this=$this\“”
Cmds 1,src 35,inst 12,litObjs 3,aux 0,stkDepth 3,代码/src 0.00
命令1:
1:pc 0-10,src 0-34
命令1:“puts\”间接查询:this=$this\”
(0)推10#“放”
(2) push11#“间接查询:this=”
(4) 按12#“这个”
(6) 装载标量
(7) concat12
(9) 调用ESTk12
(11) 完成
>字节码0x0x7fedea044c10,参考文献1,第3纪元,内部0x0x7fedea033010(第3纪元)
Source“puts\”间接查询:this=$this\“”
Cmds 1,src 35,inst 12,litObjs 3,aux 0,stkDepth 3,代码/src 0.00
命令1:
1:pc 0-10,src 0-34
命令1:“puts\”间接查询:this=$this\”
(0)推10#“放”
(2) push11#“间接查询:this=”
(4) 按12#“这个”
(6) 装载标量
(7) concat12
(9) 调用ESTk12
(11) 完成
>字节码0x0x1009af010,参考1,历元136,内部0x0x100829a10(历元136)
Source“puts\”间接查询:this=$this“。。。
Cmds 1,src 35,inst 12,litObjs 3,aux 0,stkDepth 3,代码/src 0.00
命令1:
1:pc 0-10,src 0-34
命令1:“puts\”间接查询:this=$this”。。。
(0)推10#“放”
(2) push11#“间接查询:this=”
(4) 按12#“这个”
(6) 装载机
(7) strcat 2
(9) 调用ESTk12
(11) 完成
>字节码0x0x1009b0210,参考文献1,历元136,内部0x0x100829a10(历元136)
Source“puts\”间接查询:this=$this“。。。
Cmds 1,src 35,inst 11,litObjs 2,aux 0,stkDepth 3,代码/src 0.00
命令1:
1:pc 0-9,src 0-34
命令1:“puts\”间接查询:this=$this”。。。
(0)推10#“放”
(2) push11#“间接查询:this=”
(4) loadScalar1%v0
(6) strcat 2
(8) 调用ESTk12
(10) 完成

嗯,你正在使用一个不同的itcl主要版本…我可以用Tcl 8.6.3和itcl 4.0.2.tl复制;dr:看起来你发现了一个itcl错误。幸运的是你。好吧。然后提交了罚单-后续:loadStk
/
loadScalarStk
的区别不重要;这只是一个有效的重命名。我已经到处摸索了很多,我认为is是incrTcl中的一个bug;将代码转换为纯基TclOO(itcl4基于此构建)使其按预期工作。事实上,字节码的更改完全符合预期。我相信这是一个incr Tcl错误,可能存在于扩展安装的变量解析程序中。变量解析程序看起来很难编写,但实际上比这困难得多,这就是为什么我们从未在Tcl的公共文档中公开它们ted支持的API。
itcl::class Main {
    inherit Base
    public {
        method main_process {script} {
            uplevel $script
            # Print what is actually going on!
            puts >>[tcl::unsupported::disassemble script $script]<<
        }
    }
}
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 
<<
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 
<<