nptclのブログ

Common Lisp処理系nptの開発メモです。https://github.com/nptcl/npt

Npt Lispの紹介

Nptとは小さいLisp処理系です。
現在開発中です。

https://github.com/nptcl/npt

本ブログは、NptというLispの開発をするにあたり、 難しかったり引っかかった部分をブログに記載して行くことで、 実装の確認をあらためてしていこうという目的がありました。
それなのにNptの説明が一切ないのもどうかと思うので、 せっかくなので簡単に説明します。

Nptは「C言語のみで作成できるANSI Common Lisp」を目指しています。
半分以上はできたのかなと思っています。
ちなみにCLtL2は対象外。

現時点でバージョンはv0.1.8となっていますが、 もしANSI Common Lispの関数を全部実装できたら 不完全であっても強制的にv1.0.0に格上げして、 後はひたすらテストとバグとりをして行くことを考えています。

開発方針

開発方針を示します。

短所となりえる特徴を示します

  • 機械語の翻訳をしない
  • 拡張機能は極力実装しない
  • 実行速度が遅い
  • 開発が不安定

将来やってみたいこと

  • Threadセーフにしたい
  • sqlite3みたいにamalgamationをやってみたい

順に説明します。

C99でコンパイルできること

NptはもともとC言語に組み込んで使うことを考えていました。
いろんな環境で使えるようにC11ではなく、C99をベースに作成しています。 本当はC89にしようかと思ってたんですが、 ちょっときついなと思い、あきらめた経緯があります。

環境はFreeBSDLinux (およびWindowsANSI-C)

FreeBSDは単純に自分が使っているからであり、 Linuxはたぶんみなさんが使っているからだろうという理由です。 Gentoo Linuxで動作確認をしています。

Windowsの開発は、優先順位は落ちますが、 現時点ではコンパイルとテストコードの実施は確認しています。
開発環境はWindows 10 64bit、Visual Studio 2017を利用しています。

ANSI-C環境とは、C99標準ライブラリのみで利用できる制限付きANSI Common Lispのことです。
今は対象外としていますが、もしかしたら利用できるようにするかもしれません。 一応コンパイル時に-DLISP_ANSIとすることで利用できるのですが、 テストケースを対応させていないので、どこまで正しいかわかりません。
たぶん次のようにコンパイルすると、勝手にANSI-Cモードになります。

$ cc *.c -lm

確認してみます。

$ ./a.out
(find-class 'standard-object)
#<STANDARD-CLASS STANDARD-OBJECT>
^D
$ ./a.out --version
npt Version 0.1.8
-----
Memory size          64bit
Fixnum size          64bit
Lisp mode            ANSI-C    ★ここで確認できる
Thread mode          remove
Version              0.1.8
Build information    2019/03/30-00:19:59
-----
Execute mode         standalone
Release mode         release
Degrade mode         release
-----

可能な限りANSI Common Lispの機能のみを実装する

使い方の一つとしてC言語の組み込みを目的としているため、 拡張機能はかなり制限すると思います。

とは言っても、nptは組み込み以外でも、 作者が自分自身で利用することを考えていますので、 不便にならないよう、何らかの方法で実装はしたいです。

もしかしたらforkして別の名前で開発するかもしれません。

利用に制限はない

ライセンスを緩く設定しています。
もし気に入ってくれたのなら、好きに使ってください。

機械語の翻訳をしない

コンパイル機能は実装しません。

開発方針で実装しないと決めているので、 仮に実装できたとしてもしません。

つまりcompiled-functionを作成する方法はないということです。 存在自体はしており、例えば関数carなんかは C言語で作成してあるので、compiled-functionです。

まだ実装してないのですが、関数compileinterpreted-functionを生成する予定です。 つまりevalとほぼ同じです。

もし、IntelのCPU対応でコンパイル作りたい!なんて思い始めたら、 たぶんnptをforkして別プロダクトで作ると思います。

拡張機能は極力実装しない

GUI機能とかsocket通信機能とかは、たぶん実装しません。
これも同じですね。
作りたくなったら、forkします。

実行速度が遅い

現時点で最大の欠点です。
バグがあるとかだったら直せばいい話ですが、 こちらに関しては決定的な解決が思い浮かびません。

たぶん最適化を作っていくことである程度は改善できると思います。

利用方法によって、早い部分と遅い部分はあると思いますが、 単純にファイルを一文字ずつ読み込むプログラムを作ったところ、 sbclと比べてnptは10000倍時間がかかり、 clispと比べてnptは7倍時間がかかったという結果でした。

改善はしていきたいですが、遅い部分だと場合によっては使い物に ならないかもしれません。

開発が不安定

作者の生活が不安定なため、中断する可能性は十分あります。

Threadセーフにしたい

拡張機能の実装には消極的ですが、 自分としてはThread機能を実装したいという思いがあります。
もしかしたらThreadセーフだけでも採用するかもしれません。

sqlite3みたいにamalgamationをやってみたい

nptのソースファイルをまとめて数個のファイルにすることです。
例えば

みたいな2つのファイルにする配布形態も用意できたらいいなと思います。

現在の足りない部分

実装できていないANSI Common Lispの大きな機能は下記の通り。

  • CLOSほぼ全部 ★現在開発中
  • structure全部
  • loopマクロ全部
  • pretty printing全部
  • 環境に関する関数
  • coreファイルの読み書き
  • faslファイルの読み書き

大まかに列挙しましたが、細かい部分はその他にも穴が開いていたりします。
例えばadjust-arrayの大半の機能だったり、関数isqrtの存在だったり。

機能の欠落は「common_*.c」というファイルの最後を見ると 分かるかもしれません。