以前製作したマイコンを用いたRSSリーダの基板上で 自作のPrologインタプリタを動かしてみた。
以前に、マイコンを用いたRSSリーダを製作しました。 今回は、この基板の上で、Prologインタプリタを動かしました。 将来ロボットを作るときに便利かもしれない、と思ったためです。
ターゲットの基板はTI(かつてのLuminary micro)のLM3S6965を搭載していて、 このマイコンにはFLASHメモリが256KB、SRAMが64KB載っています。 基板には、マイコンのほかにも、シリアルフラッシュメモリ等を載せていますが、 今回は利用していません。
今回、マイコンに載せたPrologインタプリタは、自作のもので、約6000行のコードでできています。 もともとは、エキスパートシステムの記述用に設計したもので、CygwinやUNIXで動きます。 カットオペレータなども含め、一通りの機能はそろえていたはずです (書いたのが約7年前なので詳細を忘れてしまった...)。 Cygwin上で動かした状態を左に載せます。パズルの問題を解かせています。
インタプリタの 字句解析器と構文解析器はflex, bisonをそれぞれ用いて生成しています。 実行する際には、構文解析でできた木を、そのまま評価していきます。 普通のProlog処理系は、プログラムを 一度Warren's Abstract Machine を基にした仮想マシンをターゲットにコンパイルして、効率的に実行することが出来るようなのですが、 そこまではできていません。
マイコンへの移植に当たっては、 メモリが小さいので、flex, bisonが生成したコードは大きくメモリに入らないかと思われましたが、 大丈夫でした。プログラムのサイズは140KBくらいになりました。 SRAMの容量はぎりぎりで、大きなプログラムの実行はできません。
注意が必要だったのは、flexが生成する字句解析器は10KB以上の大きなバッファを 確保しようとする点で、YY_BUF_SIZEを明示的に定義する必要がありました。 そのほかにも色々な問題にぶつかりました。 セクション"ARM.exidx"が別のセクションに重なってエラーが出る、など (ここ(ねむいさんのぶろぐ 2009.05.27)で説明されています)。
左の図が、マイコンでPrologを動かしている状態。
"?- "の部分が、Prologインタプリタのプロンプトです。最初の2つの"assert(...)"の行は appendを定義しています。appendは典型的なPrologのプログラムの例題で、2つのリストを連結する方法を記述しています。
[a,b](Prologでは"["と"]"で囲んでリストを表現する)と[c]を連結して[a,b,c]を作るのにappendを用いることもできるのですが、 逆に、[a,b,c]を作るのに何と何を連結させればよいか?というのも計算できます。 それが、3つ目の行("append(X,Y,[a,b,c]),...")で、4通りあることが結果で出てきています。
次の4行目("led(0,0)")は、今回のために作成した組み込み述語led/2を使っています。一つ目の引数がLEDの番号 (ボード上に複数のLEDがあるので0から順に番号を付けている)で、2つ目がLEDがオン(1)かオフ(0)かを示します。 "led(0,0)"とすると、0番目のLEDがオフになります。 5行目のように"led(0,X)"を実行すると"X=0"と結果が得られ、0番目のLEDの状態(オフになっている)を読み取れます。
つぎに、6行目("repeat, led...,fail")ではled/2を使って、LEDを点滅させています。 細かく説明すると難しくなるので省きますが、この行を実行すると、"repeat"と"fail"の間の 節を無限に繰り返します。wait/1 はビジーウエイトのための述語で、write/1は印字のための述語です。
以前製作したマイコンを用いたRSSリーダの基板上で 自作のPrologインタプリタを動かしました。 これによって、小さなPrologプログラムであれば、マイコンでも動かすことが可能であることが明らかになりました。 ロボット制御に使うとなにかと楽しいかもしれません(何も工夫しないとすぐフレーム問題にぶち当たる気がしますが...)。
割り込みも扱いたいので、拡張して、割り込みとの親和性を高めること。 メモリ不足に陥りやすいので、その場合でもエラーリカバリができるようにすること。 ネットワークに対応させて、XMLの処理などに使えるようにすること。 などが、今後の課題です。
(2009/11/1)
(2010/3/8 改訂)