Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

:callに複雑な式を渡すと「E15: Invalid expression」を出すことがある #17

Closed
tyru opened this issue Sep 16, 2011 · 18 comments

Comments

@tyru
Copy link
Member

tyru commented Sep 16, 2011

tyru/caw.vim#12 (comment)
上は一例です(他にも.で長くメソッドチェインしまくったりすると起こったことが...)。
しかし具体的な再現条件はつかめてません。
だいたいlet _ = expressionみたいにすると回避できます。

@mattn
Copy link
Member

mattn commented Sep 16, 2011

再現する最小ケースを下さい。

@tyru
Copy link
Member Author

tyru commented Sep 16, 2011

すみません、ちょっと再現するコードを作るのに手間取ってます。
eskkでも出た記憶があるので探してみたらこのコミットがヒットしました。
vim-skk/eskk.vim@3c9fc30
Dictionaryに[]でアクセスして関数を呼び出すと起こることが多いんでしょうか...?
単純にそこだけ抜き出しても再現しないので何か別条件が絡んでそうです。

@koron
Copy link
Member

koron commented Sep 16, 2011

ああ、再現自体ができないのか。Vimスクリプトの実行のしかたを考えると、
引数として何段も重なってる=トップの関数呼び出し自体が長くなるとアウトかも
という推測はできます。

@mattn
Copy link
Member

mattn commented Sep 16, 2011

単純に

call s:popup_func_table[char](a:stash)

charがkeysにないとかそういう話ではなく?

@tyru
Copy link
Member Author

tyru commented Sep 16, 2011

その場合E716: Key not present in Dictionaryが出るはずなので違うと思います。
確かめようにもgit checkoutしてもどういう入力をしてE15が出たのか上のeskkのコミットには書かれてないので検証しようがないです。すみませんorz

@koron
Copy link
Member

koron commented Sep 16, 2011

ざっとソースコード見たけどE15出すとこオオスギワロタ
ただ強制的にabortしたとかthrowしたとかでも出せそうな雰囲気。
実は例外が起きてるけどVimがうまく補足できていないとか…

@mattn
Copy link
Member

mattn commented Sep 16, 2011

タイミングは100%ですか?

@mattn
Copy link
Member

mattn commented Sep 16, 2011

おそらくこういう形かと思います。

let bar = {}
function! bar.baz(aa) dict
 return "a" . a:aa
endfunction
let foo = {}
let foo.bar = bar " ← ここ
let _ = foo.bar["baz"]("hoge")

例えばこのfoo.barがdictでなかったとしましょう。すると...

行    6:
E15: 無効な式です: foo.bar["baz"]("hoge")

と出ます。実行したケースによって

let foo.bar = bar

let foo.bar = 0

みたくdictで無くなってたり、もしくはこの行がパスしてなかったりしませんか?

@tyru
Copy link
Member Author

tyru commented Sep 16, 2011

おそらくですがそれはないと思います。
https://github.com/tyru/caw.vim/blob/1d8f7dcb841766475932376c3b527db75ccbd2ee/autoload/caw.vim#L1150
この通り代入してる箇所は1箇所だけで、スクリプトのロード時のみです。
繰り返しロードされることはないと思うので。

@tyru
Copy link
Member Author

tyru commented Sep 27, 2011

再現しました!
https://gist.github.com/1244803
forの中ってところがミソかもしれません。

let method = 'do'
call obj[method]()

とかやってもエラー出なかったので。

@mattn
Copy link
Member

mattn commented Sep 27, 2011

なるほど

function! s:do(...)
    echomsg 's:do()'
endfunction

function! s:run()
    let obj = {'do': function('s:do')}
    for method in ['do']
        call call(obj[method], [])
    endfor
endfunction
call s:run()

だと出ないのか

@mattn
Copy link
Member

mattn commented Sep 27, 2011

あとこれはokなのね

function! s:do(...)
    echomsg 's:do()'
endfunction

function! s:run()
    let obj = {'do': function('s:do')}
    for method in ['do']
        let dummy = obj[method]()
    endfor
endfunction
call s:run()

@mattn
Copy link
Member

mattn commented Sep 27, 2011

どうやら構文解析っぽい

@koron
Copy link
Member

koron commented Sep 27, 2011

ダメパターンをそのまま転載:

function! s:do(...)
    echomsg 's:do()'
endfunction
function! s:run()
    let obj = {'do': function('s:do')}
    for method in ['do']
        call obj[method]()
    endfor
endfunction
call s:run()

あとその出力:

s:do()
Error detected while processing function <SNR>182_run:
line    3:
E15: Invalid expression: obj[method]()

ところで出力見るとs:do()は一回実行されてますよね。
で、なぜか2回目が回ってる。ということは構文解析に問題があるとすれば、for ~ in ~の方かな?
組み合わせ次第でendforまで上手く飛ばせない、みたいな。

@mattn
Copy link
Member

mattn commented Sep 27, 2011

スキップ処理だった。

diff -r 5e84f6567623 src/eval.c
--- a/src/eval.c    Wed Sep 21 20:09:42 2011 +0200
+++ b/src/eval.c    Tue Sep 27 20:39:37 2011 +0900
@@ -4013,7 +4013,7 @@

     p = skipwhite(arg);
     ret = eval1(&p, rettv, evaluate);
-    if (ret == FAIL || !ends_excmd(*p))
+    if (evaluate && (ret == FAIL || !ends_excmd(*p)))
     {
    if (ret != FAIL)
        clear_tv(rettv);

@ghost ghost assigned mattn Sep 27, 2011
@mattn
Copy link
Member

mattn commented Sep 27, 2011

これもちょっと寝かせる(何個かスクリプト動作を試す)ので、安定したら提出。

@mattn
Copy link
Member

mattn commented Sep 27, 2011

@mattn
Copy link
Member

mattn commented Sep 30, 2011

違うパッチになったけど、入ったのでclose
https://groups.google.com/d/topic/vim_dev/RWJWfL-UxTM/discussion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants