frtm の上で cons や car/cdr 等のリスト処理を行うワードを作成し,局 所変数を持った新しい言語系を作られています.今のところはディレクトリが 表示されます.また,独自拡張された frtm のアーカイブも置かれています. 幾つかの機能は本家の frtm の方にも取り入れさせて頂く予定です.
FoRTh Modoki
ver 1.4.3 Mar. 4, 2001.
Copyright (C) 1999-2001 浪花 智英 (Tomohide Naniwa)
naniwa@rbt.his.u-fukui.ac.jp
0. コンパイル
□ UNIX でのコンパイル
必要があれば Makefile を変更してください.後は make だけで frtm ができ
ます.
I. はじめに
このプログラムは FORTH を模擬したソフトですが,完全に FORTH を再現した
ものではありません.コンパイラは持ちませんが,ユーザー定義ワードでは定
数やワードを定義時に解釈します.
式の解釈は逆ポーランド記法に従って行われます.if による条件分岐.
do-while, for-loop などのループのための構造もあります.また,ワードを
組み合わせて新たなワードを作ることもできます.
現在のところ扱えるのは整数のみです.数字の入力は 10 進数,16 進数(頭に
0x を付ける),8 進数(頭に 0 を付ける)で行えます.
frtm.h の中で各種スタックのサイズ等を定義しています.それぞれ,
#define STMAX 500 ; 数値計算用スタック
#define DICMAX 100 ; ユーザー定義ワードの最大数
#define CSMAX 1000 ; ユーザー定義ワードの本体の記憶領域
#define RSMAX 500 ; ユーザー定義ワード実行用スタック
#define SSMAX 400 ; ループなどの入れ子用スタック
#define MAX_NAME 8 ; ユーザー定義ワード名の最大文字数
#define LINE 100 ; 1行の最大文字数
となっています.適宜変更してください.
II. 基本機能
□ 定義済ワード
. 10 進表示
.h 16 進表示
.o 8 進表示
cr 改行
sp 空白
+ 和
- 差
* 積
/ 商
% 余り
= 同値
< より小さい
<= 以下
> より大きい
>= 以上
! 真偽反転
1+ 1 加算
1- 1 減算
0= 0 と同値
abs 絶対値
max 最大
min 最小
dup 複製
swap 交換
drop 除去
over スタックの2番目の複製
rot スタックの上位3つを回転し,3番目をトップへ
rotr スタックの上位3つを回転し,トップを3番目へ
ndup スタックの n 番目を複製
nrot スタックを回転し,n 番目をトップへ
nrotr スタックを回転し,トップを n 番目へ
ndrop スタックの上位 n 個を除去
copy スタックの上位 n 個を複製
SP 呼び出した時点のスタックの深さをスタックのトップに追加
minus 符合変換
spaces 複数個の空白
esc エスケープコード(0x1B)の出力
help 関数名一覧
quit 終了
□ 文字列に対する処理
◇ 表示 echo
(Hello_World) echo cr
スタックには
'0dlr' 'oW_o' 'lleH'
と整数型にパックした文字列が入る.echo は文字列中に 0 が現れるまで順に
表示する.上記の例の最初の文字並びの 0 は数字の 0 で,文字の '0' では
ない.
文字列中で \ (バックスラッシュ)によるコントロール・コードのエスケープ
が可能である.利用可能な文字定数は '\n'(改行),'\t'(水平タブ), '\b'(バッ
クスペース)と '\ddd' (ddd は8進数) である.ただし,8進数の文字定数で
は最上位の数が 0 であることを仮定している.尚,これ以外の文字はそのま
ま文字列中に追加される.
◇ 文字列の分解・結合 pack/unpack
(Hello_World) unpack
スタック上に置かれたパックされた文字列を1文字ずつに分解する.スタック
には
0 'd' 'l' 'r' 'o' 'W' '_' 'o' 'l' 'l' 'e' 'H'
と分解された整数が入る.
pack
unpack で1文字ずつに分解されたスタック上の整数を,再び echo で表示で
きる文字列にパックする.
III. プログラム構造
□ 条件分岐
if endif
if else endif
仕様
が 0 以外なら を実行.
が 0 なら を実行.
制限
else ブロックは複数書ける.
例題
0 if 1 else 2 endif . cr
□ do ループ
do while
仕様
が 0 であれば終了.0 以外なら do に戻って繰り返し.
例題
1 do dup . cr 1 + dup 5 < while drop
1 do dup . sp 1 do dup . sp 1 + dup 5 < while cr drop 1 + dup 4 < while drop
□ for ループ
for loop
for +loop
仕様
終了後 n2 + 1(またはn3) を実行し,n1 より小さければ for に戻っ
て繰り返し.
I リターンスタック上の n2 をスタックに追加する.
制限
n1, n2 は非負の数とする.
例題
5 0 for I . cr loop
10 0 for I . sp 5 1 for I . sp loop cr 2 +loop
□ ワードの定義
: name ;
仕様
name を持つワードを作成する.
制限
do や for のループの中ではワードの登録はできない.
ユーザー辞書は新しく定義されたものから順に検索するため,再帰が可能になっ
ている.また,ワードを再定義しても古いワードの定義はそのまま残る.
□ 例題
・平均
: ave + 2 / ;
10 28 ave . cr
・階乗 [fact(1) = 1, fact(n) = n*fact(n-1)]
: facti 1 swap 1+ 1 for I * loop ;
: fact dup 1 = if else dup 1- fact * endif ;
10 facti . cr
10 fact . cr
・フィボナッチ数列 [fib(0) = 0, fib(1) = 1, fib(n) = fib(n-1) + fib(n-2)]
: fib dup 0= if else dup 1 = if else dup 1- fib swap 2 - fib + endif endif ;
7 fib . cr
: fibi dup 0= if else 0 1 rot 1 for swap over + loop swap drop endif ;
30 fibi . cr
20 0 for I fibi . sp loop cr
・ハノイの塔
: move1 (Move disk ) echo . swap ( from ) echo . ( to ) echo . cr ;
: hanoi dup 1 = if move1 else
3 ndup 3 ndup + 6 - minus 4 ndup swap 3 ndup 1- hanoi
3 ndup 3 ndup 3 ndup move1
1- rotr swap over + 6 - minus swap rot hanoi
endif ;
1 2 2 hanoi
1 2 4 hanoi
・N Queens
: N 2 * 3 + ;
: disp dup N ndup 0 for
dup N ndup 0 for over I =
if (Q ) echo else (. ) echo endif
loop cr drop drop
loop drop ;
: check over 0 for
3 ndup 6 ndup = if drop 0 else
3 ndup 6 ndup - abs 3 ndup 6 ndup - = if drop 0 else 1 = endif
endif
5 nrot 5 nrot drop drop
loop rotr drop drop ;
: nq dup N ndup 0 for
I over 1+ dup N 1- copy 1 check if
dup N ndup over 1+ = if dup N copy disp cr else nq endif
endif
drop drop loop ;
: queens dup 0 for I 0 nq drop drop loop drop ;
4 queens
[puzzle というワードを使って上記のハノイの塔と N Queens パズルを解く
ワードをユーザー辞書に追加することができます.]
□ 辞書コマンド
help システム定義ワード,ユーザー定義ワードの一覧を表示.
forget
という名前を持つワード以降にユーザーが定義したワードを全部消去する.
fgall
ユーザーが定義したワードを全て消去する.
def
という名前を持つワードの定義を,再評価可能な形式で表示する.
load
スタックから文字列を取りだし,その名前を持つファイルの内容を読み込み評
価する.
□ ワードの探索
ワードはシステム辞書,ユーザー辞書の順に探索される.ユーザー辞書は新し
く登録されたものから検索される.
IV. 変数
□ 変数の定義
var name
仕様
name という変数を作成する.変数は辞書に登録される.見かけ上はユーザー定義
ワードの形態を取る.name を評価すると,ユーザー辞書のインデックスがスタッ
クに保存される.
制限
変数の宣言は実行可能状態でのみ可能.ワードの定義中や,do や for のループの
中では変数の定義は出来ない.
□ 値の呼出し
@
仕様
スタックから辞書のインデックスを取りだし,その番地に含まれる数値をスタッ
クに置く.
□ 値の代入
$
仕様
スタックから辞書のインデックスと数値を取りだし,その番地に登録する.
□ 例題
var x
x @ . cr
10 x $
x @ . cr
: test x @ . cr ;
test
V. グラフィクス
UNIX 上でコンパイルした場合は X11 環境で,EOTA でコンパイルした場合
は vga モードでのグラフィクスが利用できます.
□ ワード
gm グラフィクス・モードへ
tm テキスト・モードへ
x y moveto (x, y) へ移動
x y lineto 現在位置から (x, y) まで直線描画
x y rmoveto 現在位置から (x, y) だけ移動
x y rlineto 現在位置から (x, y) だけ直線描画
x y w h rect 矩形領域の描画
x y w h rectf 矩形領域の塗り潰し
x y point 点の描画
x y w h ellips 楕円の描画
x y w h ellipsf 楕円の塗り潰し
c setcolor 色設定(0: 黒 〜青緑水赤紫黄〜 15: 白)
c setbgc 文字列の背景色の指定
n setfont フォントの指定 (0: a14, 1: 7x14bold)
x y s drawstr (x, y) に文字列 s を表示(背景はそのまま)
x y s drawistr (x, y) に文字列 s を表示(背景も塗り潰す)
cls 画面消去
□ 例題
・ 色を変えながら矩形領域を塗り潰す.
: boxes 16 0 for I setcolor 10 20 I * + dup 100 100 rectf loop ;
gm boxes
tm
・再帰図形(Koch 曲線)
: pre 5 copy drop ;
: genx 3 ndup 6 ndup - * minus 100 / swap 4 ndup 7 ndup - * 100 / + 5 ndup +
5 nrotr 4 ndrop ;
: geny swap 3 ndup 6 ndup - * 100 / swap 4 ndup 7 ndup - * 100 / + 4 ndup +
5 nrotr 4 ndrop ;
: gen 6 copy genx 7 nrotr geny ;
: keep 7 nrotr 7 nrotr pre ;
: post 9 nrot 9 nrot 4 nrot 4 nrot 5 ndup 1- ;
: line moveto lineto ;
: koch dup 0= if drop line else
pre 0 0 gen keep 33 0 gen post koch
pre 33 0 gen keep 50 -28 gen post koch
pre 50 -28 gen keep 66 0 gen post koch
pre 66 0 gen keep 100 0 gen post koch
5 ndrop
endif ;
gm 50 250 600 250 4 koch
tm
: kochs 10 setcolor 89 440 551 440 4 koch
11 setcolor 551 440 320 40 4 koch
12 setcolor 320 40 89 440 4 koch ;
gm kochs
tm
[graphics というワードを使って,boxes と Koch 曲線を描くワードをユー
ザー辞書に追加することができます]
VI. ソースコードについて.
バージョン 1.3.0 以降の FoRTh Modoki (frtm) は GNU General Public
License に従うものとします.
コメント等がいただければはげみになります.
---
(putprop '浪花 智英
'affiliation '(福井大学工学部知能システム工学科)
'e-mail '(naniwa@rbt.his.u-fukui.ac.jp)
'URL '(http://www.rbt.his.u-fukui.ac.jp/~naniwa/))