ささだです.

(2012/06/15 16:30), Yugui wrote:
>> >> +ruby_opaque_t ruby_compile_main_from_file(VALUE fname, const char* path, VALUE* error);
>> >> +ruby_opaque_t ruby_compile_main_from_string(VALUE fname, VALUE string, VALUE* error);
>>
>>  コンパイルって要りますかね.eval だけじゃ駄目なんでしたっけ.つまり,
>> ファイル名,もしくは文字列渡して実行するインターフェースだけだと不十分?

 余談ですが,このアプローチは根本的に不味いと言うことに気づきました.

 Kernel.eval(src, TOPLEVEL_BINDING) 相当を目指していると思うのですが,
このために src から作る iseq は,実は渡した TOPLEVEL_BINDING の状態に応
じて異なります.


 例で示します.

    src = "a = 1"

という場合,a というローカル変数へ代入というとても簡単なコードなんですが,

  b = binding
  eval(src, b)     # この時は,自分の環境に a を作るので,
                   # setdynamic(i_idx, 0) という命令になる
  eval("x = 1", b) # 新しい変数 x が加わるので,b の環境が増える
  eval(src, b)     # 2 つ上の環境の a へ値をセットするので
                   # setdynamic(i_idx, 2) という命令になる

 同じスクリプトをコンパイルしていますが,b の状態に応じてコンパイル結果
が異なっています.

※マルチスレッドとか考えたくないですね....


 というわけで,コンパイル結果を保存して再利用,というのは原理的に無理で
した.

 [ruby-dev:45761] で述べた rb_eval_string() だと,環境は毎回新しいもの
になるので,コンパイル結果を使い回しすることが出来ます(細かいことを言う
と,グローバルに決まるコンパイルオプションを変えたときどうなるか,は違う
のですが).

-- 
// SASADA Koichi at atdot dot net