inline #5 元の関数定義が必要な件について
関数定義は si:closure-body で取り出せて、inline でやろうとしてることはこんな感じ。
- 仮引数と実引数から、てきとーに束縛する let form を作って
- その中に関数の body を突っ込む
(defun foo (&rest args) (apply #'+ args)) => foo (si:closure-body 'foo) => (lambda (&rest args) (block foo (apply #'+ args))) ;; こんな foo の呼び出しは (defun bar (a b c) (foo a b c)) ;; こう展開できる (defun bar (a b c) (let ((args (list a b c))) (block foo (apply #'+ args))))
ところが foo が byte-compile さてれいると、その body は si:*byte-code という special form になってる。
(compile 'foo) => foo (si:closure-body 'foo) => (lambda (&rest args) (system:*byte-code "^A^B^A'^@ ^@^V^A" #(+ apply)))
これを bar の定義内に展開しても、byte-code から「si:*byte-code に byte-code を与えて実行する」ことはできないし、上手いこと同じ処理を実行してくれるように byte-compile してくれるワケでもないので、「byte-compile して実行することのできるカタチ」に変換することができない。
(defun bar (a b c) (let ((args (list a b c))) (system:*byte-code "^A^B^A'^@ ^@^V^A" #(+ apply)))) => bar ;; byte-compile しなければ実行できる (bar 1 2 3) => 6 ;; byte-compile すると system:*byte-code の実行でエラー (compile 'bar) => bar (bar 1 2 3) 不正なデータ型です: system:*byte-code: function
というわけで、byte-compile されていない関数定義がないと(今の自分には)お手上げ。
実際のところ
関数 foo が site-lisp/spam.l で定義されているとする。ふつーは byte-compile された site-lisp/spam.lc もあって、そっちを読み込む。
site-lisp/spam.lc にはもはや元の関数定義が残ってないので、つまりふつーは元の関数定義なんてのはどこを探したって見つけられない。(site-lisp/spam.lc は site-lisp/spam.l を byte-compile したものではないこともありえるので、単純に site-lisp/spam.l から読み取るというワケにはいかない。)
できる/できない は置いといて思いついた方法:
- byte-code から byte-code を実行する方法を探す、あるいは作る
- どっかに元の関数定義を保存しておくようにする
- byte-code から実行可能な byte-code を再生成する