補足説明

 

1 システムインプリメンテーション

 

本章はAZ-Prologのインプリメントに関し、ユーザが知っていた方が望ましいと思われる情報を提供しています。

 

.1.1 スタック

 

AZ-Prologの実行制御には次のスタックが使われます。

 

グローバルスタック

グローバル変数、及びReadされた項、ユニブ(=../xfy)等で内部的に作られる構造体が積まれるスタックです。

 

ローカルスタック

Prolgの実行をコントロールする制御フレーム、及びローカル変数、組込み述語の引数バッファに使われるスタックです。

 

トレイルスタック

ユニファイされた変数の情報を記録し、バックトラック時に元へ戻すために使われるスタックです。

 

尚、本システムはC言語でインプリメントされており、これ以外にマシンスタック(C言語レベルで使用されるスタック)があります。

グローバルスタック・ローカルスタック、トレイルスタックのサイズは、AZ-Prologコンパイラによって再構成されたインタープリタ、又は単独実行モジュールを生成するときに指定するようになっています。

 

.1.2 Successful pop と Last call Optimization

 

AZ-Prologでは、スタックの使用量を減らすため Successful pop Last call

Optimizationを行なっています。

 

Successful pop

ある述語が決定性の終了をしたとき(この述語の実行に「オルタナティブ(他の可能性)がない」という意味です)この節の実行に使われた制御フレーム、ローカル変数部分をローカルスタックから取り除く事を「successful pop」といいます。

このため、組込み述語を含む述語の実行が決定的に終了することによって、このゴールは再充足されなくなります(例えそれ以後にそのゴールに新しい可能性が出来たとしても、その新しい可能性は試されない)ので、次のような注意が必要です。

 

 

 

a(1).

b:-a(X),write(X),assertz(a(2)),fail.

 

 

@

 

A

 

 

?-b

1

no

 

 

ゴール@の実行は、定義節a/1が一つしかありませんので決定性の終了をし、このゴールに対応する制御フレームをローカルスタックから取り除きます。

このあとで、ゴールAにより、a/1の代替節をassertしてから、fail/0によりバックトラックしても、@が再充足されることなく、b/0の実行が失敗します。

 

非決定性の組込み述語も、決定性終了をした場合は同様です。

 

 

a(1).

b:-retract(a(X)),write(X),Y is X+1,assertz(a(Y)),fail)

 

 

@

 

A

 

 

?-h

1

no

 

 

retract/1は、引数に指定された削除を試みるべき節がヒープ領域に残っている間は非決定性の終了をし、制御フレームが残っていますが、この場合のように一つだけ定義されている節を削除した後では、決定性の終了になります。

 

 

 

 

 

 

 

 

 

 

 

Last call optimization

Prologにおいて、再帰はもっとも基本的なプログラミング技法の一つです。

次の例を見て下さい。

 

write_n(0) :-!

write_n(X) :-write(X),put(32),Y is X-1,write n(Y).

 

 

@

 

 

|?-write_n(10).

10987654321

yes

 

write_n/1は引数の値を出力し、1つずつ減じながら再帰し、引数の値が0になることによって停止します。

Write_n/1の第2節の最後のゴールを実行するとき、この節自体と、それまでの各ゴールにオルタナティブ(他の可能性)がない状態になっています。すなわち、この最後のゴール@が失敗したとしても、この節には、代替節も、各ゴールの再充足もないわけですから、この節自体に要したフレームを残さなくても良いことになります。

このようなフレームを削除することを「Last call optimization」といいます。

この制御は、特に自分自身に再帰している場合(Tail recursion)ばかりでなくともおこなわれます。

また、カットオペレータが使用されることにより節の代替節、再充足すへきゴールがカットされた場合も同様な最適化を行ないます。

リストの結合を行なうプログラムappend/3において次の3つの書き方が可能ですが、@よりもA、Bの方がスタックの消費が少なくて済みます。

 

 

@

append([A¦B],C,[A¦BC]):-append(B,C,BC).

append([],L,L).

 

 

A

append([],L,L).

append([A¦B],C,[A¦BC]):-append(B,C,BC).

 

 

B

append([A¦B],C,[A¦BC]):-!,append(B,C,BC).

append([],L,L).

 

 

このようにLast callを効果的に生かすと、スタックの使用を押え、実行も早いプログラムにすることができます。

前掲のwrite_n/1はローカルスタックが全く延びずに実行することができます。

 

 

 

 

 

 

.1.3 ガベージコレクション

 

AZ-Prologは、ヒープ領域・アトム領域・グローバルスタックのガベジコレクション(ちり集め:GC)がそれぞれの領域が不足した場合に起動されます。

 

グローバルスタックは、バックトラック時に解放されますが、前掲のwrite_n/1のようにバックトラックを起こさずに実行するものに関しては、この節の中に現れたグローバル変数が解放されません。(変数]がグローバル変数の扱いとなる)

その結果、グローバル変数領域が不足した時に、必要な変数セルとそうでない変数セルを区分けし、前者のみを回収する処理(グローバルGC)がおこなわれます。

この機構のためにwrite_n/1は、引数がいくら大きい数値であっても、スタックオーバーフローを起こさずに動くことができるのです。

尚、プログラム全体の流れの中で、部分的にバックトラックを引き起こすことで、グローバルスタックの解放を計画的に行ない、グローバルGCの発生をおこえることができます。

 

write_n1(X):write-n(X),fail.

 

 

@

 

write_n1(_).

 

write_n/1の中でグローバルスタックを多量に使用した後、fail/0で解放し、GCが発生する前に解放することができます。(ただし、@の中でGCが発生しないという事を前提とします)


2 サンプルプログラムの説明

 

AZ-Prologシステムには、Prologで書かれたプログラムが多数付属しています。これらは大別して次の3つに分類されます。

 

@

システムユーティリティプログラム、システムメンテナンスに用いられるプログラムで、一部はコンパイルされた形で提供されているもののソースです。これらは、

インストールDIR\system\pl下にあり、拡張述語として説明したもの以外にいくつかあります。

 

 

Azserv.pl

OLEオートメーションサーバー

 

error.pl

エラーメッセージメンテナンス

 

Puttxt.pl

HTMLファイル表示

 

count.pl

Prologプログラムのライン数カウンタ

 

A

リストの結合、フォーマット出力などユーザがアプリケーションプログラムを開発する上で任意にとり込んでそのまま使えるユーティリティ述語集

 

 

s_utility.pl

append/3  member/2などのリスト操作述語集など

 

 

B

完成したプログラムの見本

 

 

queen.pl

Nクイーン

 

Formula.pl

数式の展開

 

lisp.pl

Prologで書いた純LISPインタ-プリタ

 

など

 

以下ではマニュアル本文に使用法の説明されている「AzEdit」「queen」以外のプログラムのうち、特に説明が必要なものに限って簡単な解説を行なっています。

説明のないプログラムについては該当プログラム中にコメントで目的と用法が書かれていますので参照して下さい。

 

また、AZ-PrologがサポートしているOLE・オートメーション機能を利用したプログラム等、Windows独自のプログラムのサンプルもあり、Prolog以外のコードも含まれます。

 

上記@とそれらに関連するファイル、及び“AZSERV.EXEOLE・オートメーションサーバーのソース)”は、AZ-Prologのインストルディレクトリ下の“SYSTEM”というディレクトリに格納されています。

 

A、B、OLE・オートメーション機能を利用したプログラム、及びそれ以外のサンプルプログラムは、AZ-Prologのインストールディレクトリ下の"SAMPLE"というディレクトリに存在するい

lispPl

 

【概要】

 

Prologで記述したpure LISPインタープリタ

 

【起動方法】

 

-lisp.↓

Read-Eval-Printループに入ります。

S式評価はlisp_EvalXV)で、XPrologのリスト形式で評価するS式を与えるとVにその評価した値が返されます。

 

LISP言語仕様】

 

シンタックス

キャラクタコード:32以下の文字は空白文字として扱われます。

「‘(シングルクォート)」と「()」、空白」文字以外の文字はアトムを構成する通常の文字となります。大文字、文字の区別はあります。

数字のみからなるアトムは整数となります。

 

 

特殊型式は以下のものがあります。

quote x):x自身を返す

progn formlformn):

form1,‥‥,formnを順に評価、formnを評価した値を返す。

cond clause1‥‥clausen):

clause1,‥‥,clausenの第1要素を順に評価する。

最初に「nil」以外のものを返した「clause」について、第2要素以外を「prognに与えられたように評価し、その値を返す。但し、clauseでただ1つの要素しかもたないときは、その返した値自体を返す。

それ以降の「clause」の第1要素の評価はおこらない。

de function-name argumet-listbody

function-nameが(lambda argument-listbody)の大域的な名前として登録される。

 

 

特殊型式以外のものは関数呼出しとして扱われる。従って、その引数がまず順に評価され、結果のリストに関数がupplyされます。

組込関数として以下のものがあります。

 

 

 

基本5関数:carcdrconseqatom

 

 

(print x)xを出力する。値はx自体.

 

 

(+xy),(-xy):それぞれxyx-yを返す。

 

 

(read):入力したS式を返す。

 

 

(terpri):改行の出力。値はt.

 

 

(help):組込関数,特殊型式名,現在定義されている関数名を出力する。値はt.

 

 

(bye):Read-Eval-Printループを抜ける。

 

 

(gefdef fname):fnameの関数定義をラムダ式の形で返す。

 

 

(load file)(save file):現在の関数定義をファイルにロード/セーブする。

 

 

 

 

 

 

)

(de append(x y)

(cond((eq x nil) y)

(t (cons(car x)(append (cdr x) y)))))

append

(append '(1 2 3) '(4 5))

(12345)

 

etc.

 

特殊型式,組込関数共容易に拡張できるようにしてあります。

特殊型式はspecialForm_call/4,組込関数はsubr_Function/1,subr_Function_call/3に各々書き加えるようになっています。

setq」のサポートは構造上むつかしいと思われます。

eq/equalprologの通常のユニファイの働きから区別のしようがありません。

 

3 エラー・メッセージー覧

 

1

Syntax error

構文エラー。

2

Can't see the file

指定されたファイルをリードオープンできない。

3

Can't tell the file

指定されたファイルをライトオープンできない。

4

End of file encountered

ファイルエンドを越えてリードしようとした。

5

Illegal file name

ファイル名が正しく指定されていない。

6

Too many variables

節または項中の変数が多すぎる。

7

Too complex term

項が複雑すぎる。

8

builtin or C pred exist

組込み述語が既に存在しているのにそれと同じ述語名・アリティを持つユーザ述語あるいはシステム述語を定義しようとした。

9

Illegal argument supplied

組み込み述語に対して正しくない引き数が与えられた。

10

Illegal Goal

整数あるいは未代入変数をゴールとして実行しようとした。

11

Illegal clause

節として認められない。

12

Illegal define tag

システムエラー。

13

Illegal throw tag

throw述語の引数のタグ指定が不正だった。

14

Illegal catch tag

catch述語の引数のタグ指定が不正だった。

15

unknown predicate call

unknown(_,error)を実行後定義されてないゴールを実行しようとした。

16

Heap area exausted

ヒープ領域(プログラムを入れておく領域)がオーバーフローした。

17

Trail stack overflow

トレールスタックがオーバーフローした。

18

Global stack overflow

グローバルスタックがオーバーフローした。

19

Local stack overflow

ローカルスタックがオーバーフローした。

20

Malloc failed

メモリアロケーションが出来ない。

21

No more break

ブレークレベルが深くなりすぎてこれ以上ブレーク出来ない。

22

Division by 0

0による除算を実行しようとした。

23

Too complex arithmetic

数式が複雑すぎて評価出来ない。

24

Overflow

フロート演算の結果が大きすぎる。

25

Underflow

フロート演算の結果が小さすぎる。

26

Illegal Arithmetic

値のセットされていない変数などが入った式を評価しようとした。

27

Illegal character code

漢字コードにないキャラクタコードを指定した。

28

Edit buffer no space

エディタバッファがオーバーフローした。

29

Kill buffer no space

キルバッファがオーバーフローした。

30

out of buffer

e_jump/1でバッファ内にない位置を指定した。

31

^Gerror

CTRL-G がコンソールから入力された。

32

Search string is too long

検索しようとした文字列が長すぎる。

20

user errors limit

error/1でユーザエラーの限界を越えた。

255

abort

abort/0を実行するとこのエラーが発生した事になりerrorset/2で受け止める事が出来る。

 

4 エデイタ(AzEdit)コマンドー覧

 

カーソルの移

CTRL-F

CTRL-B

CTRL-N

CTRL-P

ESC-F

ESC-B

CTRL-A

CTRL-E

CTRL-V

CTRL-Z

ESC-<

ESC->

CTRL-X CTRL -X

ESC-Space

カーソルを一文字前に移動

カーソルを一文字後ろに移動

カーソルを一行下に移動

カーソルを一行上に移動

カーソルを現在の単語の次に移動

カーソルを一つ前の単語の先頭に移動

カーソルを行の先頭に移動

カーソルを行の最後に移動

次の画面を表示

前の画面を表示

カーソルをテキストの先頭に移動

カーソルをテキストの最後に移動

カーソルとマークの交換

カーソルの位置にマークを付ける

(Forward character)

(Backward character)

(Next line)

(Previous line)

(Forward word)

(Backward word)

(End of line)

(View the next screen)

 

 

 

 

(Exchange)

挿入と削除

Return

CTRL-O

Tab

CTRL-Q

CTRL-D

BS,CTRL -H

NLをカーソルの前に挿入

NLをカーソル位置に挿入

タブをカーソルの前に挿入

特殊文字の挿入

カーソル位置の文字を削除

カーソルの前の文字を削除

 

(Open line)

 

(Quoted insert)

(Delete character)

(Back Space)

 

 

 

 

 

ESC-D

ESC-BS

CTRL-K

CTRL-W

CTRL-Y

カーソルのある単語を削除

カーソルの一つ前の単語を削除

カーソルより右を削除

カーソルとマークの間を削除

ESC-D,CTRL-K,CTRL-Wで削除し

たテキストをカーソルの前に挿入

(Delete word)

 

(Kill line)

(Kill region)

(Yank)

探索と置

CTRL-S文字列ESC

CTRL-R文字列ESC

CTRL-S CTRL-S

CTRL_RCTRL-R

ESC_R 文字列1ESC

文字列2ESC

ESC-Q 文字列1ESC

文字列2ESC

 

前向きの探索

後ろ向きの探索

同じ文字列の前向き探索

同じ文字列の後ろ向き探索

文字列1を文字列2に置き換える

文字列1を文字列2にキーボードからの指示に従い置き換える

(Search)

(Reverse search)

 

 

(Replace)

 

(Query replace)

ファイル操

CTRL-X CTRL-V ファイル名

CTRL-X CTRL-I ファイル名

CTRL-X CTRL-W ファイル名

ファイルをバッファに読み込む

ファイルをバッファに読み込む

テキストをファイルに書き出す

(Visit file)

(Insert file)

(Write file)

プログラム領域への転

CTRL-X CTRL-S

CTRL-XS

テキスト全体のreconsult

領域のreconsult

バッファの領域確保・切替・切り離し

CTRL-C

CTRL-X CTRL-B

CTRL-X CTRL-C

バッファの切替

バッファの領域を確保

バッファを切り離し(領域開放)

AzEditの終了

CTRL-X CTRL-Z

CTRL-XZ

PROLOGへ戻る

画面の下の部分にスクロール領域を設定してPROLOGへ戻る

その他のコマンド

CTRL-L

ESC-+

ESC

ESC-W

ESC-U

ESC-L

ESC-C

カーソルを中心に画面を再配置

AzEditの使用する行数を一行増やす

AzEditの使用する行数を一行減らす

AzEditの使用する行数を最大にする

単語を大文字に変換

単語を小文字に変換

単語を先頭だけ大文字に変換

(Upper case)

(Lower case)

(Capitalize)

 

 

 

 

 

 

 

 

5 コンソール ヒストリ、テンプレートコマンド一覧

 

ヒストリ

CTRL-X

ヒストリーの表示

テンプレー

CTRL-F

CTRL-A

CTRL-E

CTRL-W

CTRL-T

CTRL-Q

CTRL-U

現在の行にテンプレートから1文字コピーする

現在の行にテンプレートに残っている全ての文字をコピーする

テンプレート内の1文字をスキップする

挿入モードに入る。もう1度押すと挿入モードを解除する

現在の行の内容をテンプレートにコピーする

現在行の先頭まで戻り最初の2文字をスキップする

現在のテンプレートより一つ古いヒストリーをテンプレートにコピーし同時に現在行の最初からコピーする(CTRL-A)

(最初のCTRL-UCTRL-Aと同じ)

現在のテンプレートより一つ新しいヒストリーをテンプレート

にコピーし同時に現在行の最初からコピーする(CTRL-A)

 

CTRL-N

 

<<ご注意>>

()

本書の内容の一部または、全部を無断で転載することは、その形態を問わず固くお断り致します。

()

本書の内容について将来予告なしに変更することがあります。

()

本書の内容につきましては、万全を期して作成致しておりますが、万一誤り、お気付きの点がございましたら、ご連絡下さいますようお願い致します。

()

運用した結果の影響につきましては、(3)にかかわらず責任を負いかねますのでご了承下さい。