2022/08/08

 

 

Vim9 scriptのバグの原因をつきとめたー

眠いと体調が終わるので今日は早く寝ます

 

 

詳細

要はVim scriptでは関数と変数で名前空間が分かれているのに、Vim9 scriptでは変数にそのまま関数を代入できるので世界が交わってしまう←ちょっと妥協が入っている(こちらの方が便利なので)

んで、Vim9 scriptではs:Hogeという変数があるとき、s:Hogeは変数なのか関数なのか関数の参照なのかをVMアセンブリコンパイルする時に判断しないといけないけれどもそのメソッドに考慮漏れが(多分)ある

という問題

 

まだ、Vim9 scriptのコードは見てないからわからんけど

 

目標:

⭐️模試、⭐️Vimのバグをもう一つ見つけてあるので報告、⭐️勉強、Keewebの翻訳、Keewebの漢字が中華フォントなのを直す

 

 

⛳️思考のログ(vim-jpにポストしたやつ)

Vim9 scriptでs:hoge()などの参照を取れない、また、s:hoge()などスクリプトローカルな小文字から始まる関数をうまく扱えない


・Vim9 scriptでは関数を呼び出すタイミング / defcompileのタイミングでs: / g: 変数の存在を確認している

コンパイル時に変数が宣言されているかどうかで挙動が変わる

let s:Hoge = "UNKO"

def! Foo()
echo s:Hoge
call s:Hoge()
enddef

" Fooはここでコンパイルされる
disassemble Foo

function! s:Hoge()
echo "hoge called"
endfunction

call Foo()

 

let s:Hoge = "UNKO"

function! s:Hoge()
echo "hoge called"
endfunction

def! Foo()
echo s:Hoge
call s:Hoge()
enddef

" Fooはここでコンパイルされる
disassemble Foo

call Foo()

 

↑の場合は s:Hoge は変数として読み出されるのでcallできずに死ぬ
↓の場合は s:Hoge は関数として読み出されるので、echo s:Hogeもcall s:Hogeもs:Hogeを関数として処理する

 

 

 

 

コンパイル時にs:Hogeなどの名前が関数の名前空間に属しているか変数の名前空間に属しているかは次の手順で判定される(たぶん(挙動を見る限り))
名前のスコープ(s:/g:/b:)を取っ払った時変数が大文字から始まるか小文字から始まるかをみる
 →大文字の場合:名前が関数の名前空間に属しているか変数の名前空間に属しているか確かめる
  →関数の名前空間:関数としてコンパイル(PUSHFUNC)する
  →変数の名前空間:変数としてコンパイル(LOADS)する
  →両方:関数としてコンパイルする(PUSHFUNC)
 →小文字の場合:名前が変数の名前空間に属しているか確かめる
  →属している:変数としてコンパイル(LOADS)する
  →属していない:エラーを吐く

関数と変数が同時に同じ名前が存在している場合関数が強制的に読まれる問題はさておき、
関数がスクリプトローカルスコープにあるとき、関数名として小文字から始まることが許可されるので これだとスクリプトローカルの関数をVim9 scriptから呼び出しできなくて困る

 

let s:hoge = "HOGE"
def! s:hoge()
echo "s:hoge"
enddef

def! s:foo()
hoge = "HOGEEEEEEEEE"
echo s:hoge
enddef

" Fooはここでコンパイルされる
disassemble s:foo
call s:foo() # => "HOGEEEEEEEEEE"

 

let s:Hoge = "HOGE"
def! s:Hoge()
echo "s:hoge"
enddef

def! s:foo()
Hoge = "HOGEEEEEEEEE"
echo s:Hoge
enddef

" Fooはここでコンパイルされる
disassemble s:foo
call s:foo() # => <SNR>412_HOGE

代入文のときは常に変数としてコンパイルされるみたいです。関数の名前空間に代入はできないので