sitelogo
CからIF/Prologへのインタフェースの使用
MINERVA superseeded IF/Prolog. Please see http://www.ifcomputer.co.jp/MINERVA for details.

We discontinued to sell IF/Prolog Dec 31. 2003. For current customers, we continue to provide professional support for IF/Prolog until Dec 31, 2008.

概 略

#include "cpro.h"

main(argc,argv) { QueryDescr *Descr;

. . . initialising C code . . .

InitParms(" ",&ARGC,ARGV); InitProlog(ARGC,ARGV,IN,OUT,ERR);

. . . more C code . . .

ParseProlog(" ", &Descr);

RunProlog(Descr); /* first solution */

. . . more C code . . .

while( RunProlog(Descr) == 1 ) /* further solutions */ { if Descr->ret_code < 0 { . . . error . . . } else { . . . . . = Descr->var[i].loc.term/* QuTerm(Descr,i+1)*/ . . . } }

EndProlog(); . . . }

<IF/Prologとの接続>

変数は、IF/Prologと呼び出し元のCプログラムの間で、変数記述子の配列をもつ質問記述子によって受け渡しされます。

ParseProlog()は、初めに質問記述子を生成/更新します(注意:質問記述子は参照によって引き渡されなければなりません)。RunProlog()は、実行の結果によって質問記述子を更新します。ユ−ザも変数記述子を操作することができます。(特にtypeフィ−ルド)

<基本的な必要条件>

ファイル"cpro.h"は、このインタフェ−スを使うどのCソ−スファイルにも含まれていなければなりません。

<第一段階>

固定された質問(動的に生成されていない)は、初めにParseProlog()によって構文解析され、その質問記述子はセ−ブされます。このことは、何度も実行が繰り返される質問にとって特に有効です。

<質問記述子の構文解析>

(QueryDescr,ParseProlog()の説明も参照して下さい)

ユ−ザは、QueryDescr(構造へのポインタ)を宣言し、それを参照によってParseProlog()に引き渡さなければなりません。

質問の文字列の構文解析が成功した場合、ret_codeは1となり、質問記述子の各フィ−ルドは前述のようにセットされます。var[]はn個の変数記述子の配列です。

構文エラ−がある場合には、ParseProlog()が-1を返します。質問の文字列の中で構文解析が中断された文字の場所は、parse_posによって示されます。

<質問の実行>

(QueryDescr,RunProlog()の説明も参照して下さい)

RunProlog(Descr)は、Descr->qu_idによって識別された質問の実行を開始、または継続します。前もってDescrを引数として、ParseProlog()が呼び出されていなければなりません。

ユ−ザは、各変数のデ−タ型の表現を選択することができます。これは、RunProlog()を呼び出す前に、var[i].type, var[i].locをセットすることによって行います。デフォルトはIF/PrologのTERMであるQ_TERMです。しかしユ−ザは、型をQ_INTEGER(long), Q_DOUBLE, Q_STRINGのいずれかに設定することによって、返り値をホスト言語(C)の変数として受け取ることもできます。

RunProlog()の最初の呼び出しで質問の実行が開始され、成功すれば1が返され、最初の解が*var[*].loc.に与えられます。次の呼び出しは、違う質問に対して、ParseProlog()やRunProlog()が呼び出されなければ成功して1を返し、バックトラックによってさらに他の解が得られます。もうそれ以上他の解が得られず、実行が失敗した場合には、RunProlog()が0を返します。質問を再開するためには(最初の解を見つけ、そこから継続する)、IF/Prologの実行に用いたスタックをクリアするマクロResetQueries()を使います。

実行中にエラーが生じた場合には(単なる失敗ではなく)、RunProlog()が-2を返し、ret_msgからメッセージが得られます。そのメッセージは以下のいずれかとなります。

・通常のシステムで出される例外メッセージ 例えば"EXCEPTION: atom_expected: goal(..)","stack_overflow"...

・ユーザが出す例外メッセージ(raise_error/1)

-3が返された場合には、IF/Prologのアプリケ−ションが述語end/0bye/0, abort/0,exit/1のいずれかによって終了されています。exit/1はユーザの定義した終了コードをフィールドexit_codeに引き渡すのに使われます。 違う質問(記述子)でRunProlog()を呼び出したり、前の質問に対する解を持たない質問記述子でParseProlog()を呼び出すと、新しい質問の実行が始まる前に、スタックから前の質問に対するその他の解が削除されます。

<変数の取扱い>

(VarDescrとマクロ定義を参照して下さい)

質問中の各変数は、ParseProlog()による構文解析で生成される質問記述子中の配列var[i]の要素によって記述されます。

構文解析の後でも質問の実行の前であれば、ユーザは変数値の型をデフォルト(IF/PrologのTERM)から望みのCのデ−タ型(long,double,string)へ変換するように指定することができます。この型設定を簡単にし、C変数ポインタを値のアドレスに結合するために3つのマクロ定義が"cpro.h"にあります。これらは、QuLOCInt(descr,1,int_ptr), QuLOCDbl(descr,1,dbl_ptr), QuLOCStr(descr,1,str_ptr)です。

変数がTERMのまま残された場合は、以下のマクロ関数がTERMを変換し、Cの変数値を返します。これらは、QuIntPC(descr,i), QuDblPC(descr,i), QuAtStr(descr,i)です。

マクロ関数QuType(QuTerm(descr,i))は変数のIF/Prologの型をチェックし、TERMが変換されるべきCの型を示す、Q_TERM, Q_INTEGER, Q_DOUBLE, Q_STRINGのいずれかを返します。マクロ関数QuTerm(descr,i)は、単にその変数の値を表わしています。

<質問のセ−ブと再使用>

前回のParseProlog( ,&Descr)の呼び出しに質問記述子が使われている場合、Descrによって記述されているその質問はセ−ブされています。IF/Prologは、自動的に複数の質問記述子をQuMaxNumにセ−ブします。しかし、それらに対する解はセ−ブしません。 質問には、頻繁に使われたり、繰り返し使われるものがあります。そのような質問は1度だけ構文解析し、あとはCインタフェ−スにセ−ブしておいて使用するのがいいでしょう。 たとえば QueryDescr *RES; QueryDescr *CLRSCR; QueryDescr *BREAK;

ParseProlog("reset_streams.",&RES); ParseProlog("clear_screen.",&CLRSCR); ParseProlog("break.",&BREAK);

質問はシステムによってセ−ブされ、以下の呼び出しによっていつでも実行できる状態になっています。

RunProlog(RES); /* to reset i/o streams */ RunProlog(CLRSCR); /* to clear the screen */ RunProlog(BREAK); /* to enter IF/Prolog top level loop */

-構文解析が成功しなかった場合 -セ−ブ可能な質問の最大数(QuMaxNum)に達した場合 -すでに別のParseProlog()の呼び出しに使われていた場合

<終了とIF/Prologからの復帰>

C言語からPrologへのCインタフェ−スは、前述のIF/Prologシステムと十分に互換性を持つように設計されています。標準"main.c"は、単にIF/Prologのコマンドインタプリタのトップレベルル−プを呼び出します。

IF/Prologから抜け出る述語(end/0, bye/0)の意味は、変更されます。これらの述語は実行を完全に終了するというよりは、むしろ呼び出し元のC関数に復帰することになります。これらはret_codeを-3にします。

述語exit/1はユ−ザの定義した終了コ−ドを(その引数として)、フィ−ルドexit_codeのホストCプログラムに渡します。この場合ret_code=-3となります。

CプログラムがもうIF/Prologのセッションを必要としなくなった時には、IF/Prologに割り当てられたメモリを開放するためにEndProlog();が呼び出されなければなりません。

<IF/Prologのトップレベルル−プの開始>

IF/Prologのインタプリタル−プは、break/0の呼び出しによって開始されます。これは、通常の対話型のIF/Prologのセッションを開始します。この状態でのみ、debug_modeとtrace_modeをオンすることができ、あるいは指令debugとtraceが実行できるのです。 たとえば、?- debug.

<リンケ−ジ>

IF/Prologのオブジェクトライブラリ−とあなたのアプリケ−ションをリンクするだけでいいのです。(IF/Prologによるcursesライブラリ−の使用は、minitc.cを使うことによって省略できます)

ifcc main.c iflink -h newprolog main.o


Up read on...
scroll to top managed with ubiCMS