Chap. 6 Programming Tips

# Programming Tips

English version

- 引数の数が異なる述語を定義する
- C++で組み込み述語を実装する

### 引数の数が異なる述語を定義する

通常の述語の型定義に加えて，それぞれの述語についての型を定義する必要があ ります．例えば，`Z=X+Y`を計算する述語 `inc(X,Y,Z)`を定義するとき，`Y`が省略された場合は `Y=1`とする述語`inc(X,Z)`も定義したいとします．そ のとき，3引数の述語の型'inc/3'と2引数の述語の型'inc/2'を定義します．

>     inc <- [pred].
>     'inc/2' <- ['pred/2', inc].
>     'inc/3' <- ['pred/3', 'inc/2'].

'inc/2', 'inc/3' はそれぞれ2引数，3引数の述語に対する型です．'pred/2', 'pred/3'は全ての2引数，3引数の述語の親の型です．'inc/2', 'inc/3'ともプロ グラム中ではincという型で記述されるので，inc と単一化可能である必要があ ります．また，'inc/3'はincの直接の子供にはなれない('pred/3'は'pred/2'の 子なので，incと'pred/2'とのleast upper boundが複数できてしまう）ので， 'inc/2'の子供として定義します．また，/は型名には使えないので，''で囲む必 要があります． このように型を定義すると，引数の数が異なる述語を定義することができます．

>     inc(X, Y, Z) :-
>         Z is X + Y.
>     inc(X, Z) :-
>         inc(X, 1, Z).

通常の述語の型定義は`inc <- [pred].`だけですみますが，実際 には`'inc/3' <- ['pred/3', inc]`という型も自動的に生成され ています．引数の数が異なる述語を定義するときは，これを明示的に定義する必 要があるわけです．

### C++の組み込み述語を実装する

LiLFeS では，C++のプログラムを簡単に組み込むことができます．例えば， `Z=X+Y`という計算を行う組み込み述語`add(X,Y,Z)`の C++による実装は，以下のようになります．

>     // まず，第一引数が machine クラス，残りが FSP，返り値が bool の
>     // 関数を実装します．
>     bool add(machine& m, FSP arg1, FSP arg2, FSP arg3 )
>     {
>       // ここ以下では，FSP クラス (structur.{h,cpp} で定義されている)
>       // のインスタンスである arg1, arg2, ... を使って，述語の引数に
>       // アクセスします．

>       // まず，エラーチェックをします．ここでは，arg1, arg2 は integer
>       // でなければならないので，そのチェックを行います．
>       // 素性構造の処理のためのいろいろなメソッドは FSP クラスで
>       // 提供されています．
>       if ( ! arg1.IsInteger() || ! arg2.IsInteger() ) {
>         // どちらかが integer で無い場合は，メッセージを表示します．
>         // RUNWARN はランタイムワーニングのメッセージを表示するマクロです．
>         RUNWARN( "Arguments of 'add/3' must be integers" );
>         // 組み込み述語を fail させるには，false を返します．
>         return false;
>       }

>       // 引数の素性構造を C++ の int 型に変換します．
>       int X = arg1.ReadInteger();
>       int Y = arg2.ReadInteger();
>       // Z = X + Y を計算します．
>       int Z = X + Y;

>       // 結果の整数を素性構造に変換します．
>       FSP result = FSP( m, Z );

>       // 結果の素性構造を第3引数と単一化します．
>       // 単一化が成功すれば true, 失敗すると false が返ってきます．
>       if ( ! arg3.Unify( result ) ) {
>         // 単一化が失敗した場合は，この組み込み述語も失敗させます．
>         return false;
>       }
>       // 組み込み述語の実行が成功した場合は，true を返します．
>       return true;
>     }

>     // この関数を lilfes の組み込み述語として登録する場合は，
>     // LILFES_BUILTIN_PRED_X というマクロを使います．X は述語の
>     // 引数の数です．第一引数は C++ の関数名，第二引数は lilfes
>     // での述語名です．
>     LILFES_BUILTIN_PRED_3(add, add);

以上のようなインタフェースでプログラムを実装すれば，どのようなC++ プログ ラムも LiLFeS に組み込むことができます．素性構造の処理は FSPクラスを使っ て行い，抽象機械の操作（ヒープやスタックへのアクセスなど）は machine ク ラスを使って行います．その他，組み込み述語を実装するときに便利なマクロや 関数はbuiltin.{h,cpp}で定義されていますので，そちらを参照してください．

5章 エラーメッセージ

目次 LiLFeSドキュメント LiLFeSホームページ 辻井研究室