試しにC言語でCommon Lispを使う
npt
の開発は結構進んでおり、
あとはcompile-file
, load
, step
だけとなりました。
まあバグを含め問題盛りだくさんなんですけどね。
npt
の開発目的の一つとして、C言語に組み込んで使うという考えがあります。
だからわざわざnpt-amalgamation
という訳の分からないものも作っています。
C言語の組み込みは、自分にとっては結構大切なものなので、 少しくらいは外部インターフェイスを作ろうかと頑張っていたのですが、 やはりなかなか難しいものです。
例えば下記のLispのコードを考えます。
(defun fact (x) (if (not (plusp x)) 1 (* x (fact (1- x))))) (defun test () (format t "Fact: ~S~%" (fact 200))) (test)
単なる階乗です。
これをnpt
のモジュールを使って、C言語で表してみます。
★ただし問題ありバージョン。
addr fact(addr x) { addr y; if (! lisp_plusp(x)) return lisp_fixnum(1); lisp_funcall8(&y, "-", x, lisp_fixnum(1), NULL); lisp_funcall8(&y, "*", x, fact(y), NULL); return y; } int test(void) { addr value; value = fact(lisp_fixnum(200)); lisp_format8(lisp_t(), "Fact: ~S~%", value, NULL); return 0; }
実際に動かした結果は下記の通り。
Fact: 78865786736479050355236321393218506229513597768717326329474253324435944996 34033429203042840119846239041772121389196388302576427902426371050619266249528299 31113462857270763317237396988943922445621451664240254033291864131227428294853277 52424240757390324032125740557956866022603190417032406235170085879617892222278962 3703897374720000000000000000000000000000000000000000000000000
初期化などを抜かした一部抜粋ですが、こんな感じになりました。
個人的には割といいんじゃないかと思うんです。
もし上記のようにラフに使えるなら、
便利なモジュールになるんじゃないでしょうか。
でもダメ。
上のコードはGarbage Collectionのタイミングでメモリ破壊をおこします。
これ、なんて言うんでしょうか。
メモリリークの逆なんですよね。
C言語上だとまだ使ってるのに、Common Lispではもういらないだろうと判断して
勝手にメモリを開放していくやつなんですが、
npt
の開発では本当に頻繁に起こります。
検索すると、C#
とかでも生じる現象みたいです。
たぶんGarbage Collection型のメモリを持った環境だと
典型的な問題なんだと思います。
もちろん対策する方法はあるのですが、 普通の人にメモリ破壊が起きないように C言語でコードを書いてくださいと言われても無理でしょう。
Lispのモジュール化というのもなかなか難しいものです。
まあこのまま作っていく予定ですが。