2017-05-03 23 views
2

從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_process_directworker_process_both功能始終提供正確的結果。但worker_process_inderect只適用於舊版本的Tcl/Itcl。對於Tcl 8.6.6/Itcl 4.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 = ::worker 
Tcl 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,我還沒有發現顯著的變化?

+0

那麼,你使用了不同的主要版本的itcl ...我可以用Tcl 8.6.3和Itcl 4.0.2重現。 –

+0

** tl; dr **:您看起來像是發現了一個itcl錯誤。幸運的你。 –

回答

2

現在就是非常好好奇!我增強你的腳本,定義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使用loadStkloadScalar1將變量載入tw o案例。這很奇怪;我不希望loadScalar1出現在一個腳本片段(它需要一個本地變量表),但至少它正在提取預期值,而loadStk只是完全錯誤的值。我也嘗試在兩個地方使用完全相同的值 - 腳本保存在一個共享變量中 - 但產生相同的輸出;它看起來像在一個地方,它正在評估,但拿起了錯誤的價值(可能是一個變量解析器問題?),另一方面,它正在挑選正確的價值,但由於錯誤的原因(因爲LVT不應該用於腳本片段;僅適用於完整的程序/方法)。無論哪種方式,這都是壞消息。

請在http://core.tcl-lang.org/tcl/tktnew上提交錯誤報告,因爲這聽起來像幾種錯綜複雜的行爲。

+1

好的。提交票 - 然後 - http://core.tcl-lang.org/tcl/tktview/a1d08eb5353fd6fc39ed8b480f011af7bd875666 – GrAnd

+0

後續:'loadStk' /'loadScalarStk'差異無關緊要;這實際上是一次重命名。 –

+0

我探討了更多,我認爲這是incrTcl中的一個錯誤;將代碼轉換爲純粹的基本TclOO(itcl 4構建於其上)使其按預期工作。 –