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 を再生成する