FORTH電卓用言語(Real Forth)


概要

この「FORTH電卓」ではFORTH (Forth(Wikipedia)参照) 風の逆ポーランド記法の式を計算することができます。 逆ポーランド記法では演算子を後に記述します。 例えば

2 3 +
と書くと「2 + 3」を表します。
2 3 + .
と書くと「2 + 3」の結果を表示します。「.」は結果を表示することを表します。

FORTHでは整数を扱いますが、このFORTH風言語ではJavaScriptで実装しているため、データは浮動小数点の数値を扱います(仮にReal Forthと呼ぶことにします)。

FORTHでは、データはデータスタックというスタックに入ります。 スタックは後から入れたものから順に取り出すことができます。 上記の例では「2」でスタックに 2 が入ります。 その後「3」でスタックに 3 が入ります。 これを取り出すときは 3 から順に取り出すことができます。 「+」で 3 と 2 を取り出し、2 + 3 の結果 5 をスタックに入れます。 「.」で 5 を取り出し、表示します。 FORTHではデータスタックのデータは整数ですが、 この言語では浮動小数点の数値となります。

FORTHでは、リターンスタックというスタックがあって、 システムが実行時の情報を管理するために使われています。 そのスタックをユーザーも使うことができます。 この言語では、リターンスタックに相当するスタックがありますが、 実行時の情報は入っていません(仕様が不明だしデータを浮動小数点にすると実装できるかどうかわからないため)。 このスタックをユーザーが使うことができます。

値を真理値として考えるときは、0 のときは偽、それ以外のときは真とします。

グラフィックス領域は最大横640ピクセル、縦640ピクセルとします。 グラフィックス領域に描画される疑似グラフィックスは最大横80ピクセル、縦80ピクセルとします。

電卓モード・実行モード

この言語の実装では、ワードは文字列で管理されています(電卓モード)。これを数値の列に変換(コンパイル)して実行することもできます(実行モード)。

ワードの定義

「+」、「.」などはワードと呼びます。 式は、ワードまたは数値または名前の列で構成されます。 これらを(わかりにくいですが)文字列と呼ぶことにします。 文字列はスペースで区切ります。 ワードはユーザーが定義することができます。 定義せずに最初から使えるワード(標準ワード) は大文字と小文字の区別はありません。 ユーザーが定義するワードの大文字と小文字は区別されます。

ワードは

: ワードの名前 文字列 … ;
という文字列の列で定義します。定義の後、ワードの名前がこの文字列の列を表します。

定数・変数

FORTHでは定数と変数を使うことができます。 この言語でも使うことができますが、定義されてからFORGETワードで削除されるまで使うことができるとします(元のFORTHで使用できる範囲は不明)。 この範囲は「電卓モード」(後述)では実行順、「実行モード」(後述)では書かれた順とします。 定数名と変数名の大文字と小文字は区別されます。

定数は

定数の値 CONSTANT 定数の名前
という文字列の列で定義します。定義の後、定数の名前がこの定数の値を表します。 定義する前に使用することはできません。

変数は

変数の値 VARIABLE 変数の名前
という文字列の列で定義します。変数にはアドレスがあり、定義の後、変数の名前がこの変数のアドレスを表します。 定義する前に使用することはできません。

FORGET 定数または変数の名前
で定数または変数の定義を消去することができます。 この後は消去した名前で定義することができます。

定数と変数の定義については、FORTHの仕様とは異なるかもしれません。

制御構造

IF … THEN

条件 IF 真の列 THEN
は条件が真のとき真の列(文字列の列)が実行されます。 条件が偽のときは何も実行されません。
条件 IF 真の列 ELSE 偽の列 THEN
は条件が真のとき真の列(文字列の列)が実行されます。 条件が偽のときは偽の列(文字列の列)が実行されます。

真の列、偽の列には他の制御構造を含むことができます(ネストと呼びます)。

DO … LOOP

終了値 初期値 DO 文字列の列 LOOP
は、まず制御変数の値を初期値にして、文字列の列を実行します。 制御変数の値に1を加えて、終了値までの範囲内にあるときは文字列の列を再び実行します。 これを制御変数の値が範囲外になるまで繰り返します。 制御変数とは、このループに付随する変数で、ループの実行中存在します。

終了値 初期値 DO 文字列の列 増加分 +LOOP
は、まず制御変数の値を初期値にして、文字列の列を実行します。 制御変数の値に増加分を加えて、終了値までの範囲内にあるときは文字列の列を再び実行します。 これを制御変数の値が範囲外になるまで繰り返します。 制御変数とは、このループに付随する変数で、ループの実行中存在します。

文字列の列には他の制御構造を含むことができます(ネストと呼びます)。

BEGIN … REPEAT、BEGIN … UNTIL

BEGIN 条件 WHILE 文字列の列 REPEAT
は条件が真である間、文字列の列を繰り返し実行します。

BEGIN 文字列の列 条件 UNTIL
は文字列の列を実行し、 さらに、条件が真になるまで、文字列の列を繰り返し実行します。

文字列の列には他の制御構造を含むことができます(ネストと呼びます)。

標準ワード

標準ワードにはFORTHのワード、プログラム電卓由来のもの(S-BASIC、Quick BASIC由来、C#由来の関数)などがあります。(1)、(2)などの番号はスタックから取り出す順を表します。

ワード パラメーター 結果 説明
. x なし x を結果領域に表示します。
SWAP x, y y, x スタックの(1)と(2)を入れ替えます。
DUP x x, x スタックの(1)を取り出さず、さらに(1)を入れます。
-DUP x 説明を参照 スタックの(1)が真のときはスタックの(1)を取り出さず、さらに(1)を入れます。スタックの(1)が偽のときは何もしません。
?DUP
OVER x, y x, y, x スタックの(1)、(2)を取り出さず、さらに(2)を入れます。
ROT x, y, z x, y, z, x スタックの(1)、(2)、(3)を取り出さず、さらに(3)を入れます。
DROP x なし スタックの(1)を取り出します。
PICK x(n),…,x(1) x(n),…,x(1),x(n) スタックから何も取り出さず、(n)を入れます。
ROLL x(n),…,x(1) x(n-1),…,x(1),x(n) スタックから(n)を取り出し、(n)を入れます。
DO x, y なし スタックから(1)、(2)を取り出し、(1)をループの制御変数の初期値、(2)を終了の値として、次の文字列からLOOPまたは+LOOPまでを繰り返します。
LOOP なし なし (ネストを考慮し)対応するDOの制御変数の値を1増やして、 範囲内であればDOの次の文字列に戻り、 範囲外であれば次の文字列に進みます。
+LOOP x なし スタックから(1)を取り出し、 (ネストを考慮し)対応するDOの制御変数の値を(1)の値だけ増やして、 範囲内であればDOの次の文字列に戻り、 範囲外であれば次の文字列に進みます。
I なし 説明を参照 (ネストを考慮し)対応するDOの制御変数の値をスタックに入れます。
J なし 説明を参照 (ネストを考慮し)対応するDOのもう一つ外側のDOの制御変数の値をスタックに入れます。
LEAVE なし なし (ネストを考慮し)対応するDOから抜けて、 LOOPまたは+LOOPの次の文字列に行きます。
BEGIN なし なし BEGIN - REPEATループまたはBEGIN - UNTILループを(次の文字列から)開始します。
WHILE x なし スタックから(1)を取り出し、(1)が真のときは次の文字列に行きます。 (1)が偽のときはループを終了し、 (ネストを考慮し)対応するBEGIN - REPEATループから抜けて、 REPEATの次の文字列に行きます。
REPEAT なし なし (ネストを考慮し)対応するBEGINの次のワードに戻ります。
UNTIL x なし スタックから(1)を取り出し、(1)が真のときはループを終了して次の文字列に行きます。 (1)が偽のときは (ネストを考慮し)対応するBEGINの次の文字列に戻ります。
IF x なし スタックから(1)を取り出し、(1)が真のときは次の文字列に行きます。 (1)が偽のときは (ネストを考慮し)対応するELSEまたはTHENの次の文字列に行きます。
THEN なし なし IF - THEN、IF - ELSE - THEN の終端を表します。
ELSE なし なし (ネストを考慮し)対応するTHENの次の文字列に行きます。
: なし なし ワードの定義を開始します。次の文字列がワードの名前となります。(「;」までがワードの定義)
; なし なし ワードの定義を終了します。 この後、このワードの名前を書くと定義されたワード(「:」から「;」まで)を実行することができます。
CONSTANT x なし 定数を定義します。次の文字列が定数の名前となります。 スタックから(1)を取り出し、定数の値とします。 この後、この定数の名前を書くと定数の値をスタックに入れることができます。
VARIABLE x なし 変数を定義します。次の文字列が変数の名前となります。 スタックから(1)を取り出し、変数の初期値とします。 この後、この変数の名前を書くと変数のアドレスをスタックに入れることができます。
FORGET なし なし 次の文字列で指定された定数または変数を削除します。 この後は、この名前の定数または変数を定義することができます。
@ x 説明を参照 スタックから(1)を取り出し、そのアドレスの変数の値をスタックに入れます。
! x, y なし スタックから(1)を取り出し、(1)のアドレスの変数の値(2)に変更します。
+! x, y なし スタックから(1)を取り出し、(1)のアドレスの変数の値に(2)を加えます。
>R x なし スタックから(1)を取り出し、それをリターンスタックに入れます。
R> なし 説明を参照 リターンスタックから取り出し、それをスタックに入れます。
INPUT なし 説明を参照 実行すると、入力領域に入力できます。 この領域に数値を入力してOKボタンを押すと、その値が結果となります。
GET なし 説明を参照 実行すると、入力領域に入力できます。 この領域に数値を入力すると、その値(入力がないときは0)が結果となります。
STOP なし なし プログラムを一時停止します。Contボタンで再開することができます。
END なし なし プログラムを終了します。
SET x, y なし 「疑似グラフィックス」の(x, y)の位置に点を描画します。
RESET x, y なし 「疑似グラフィックス」の(x, y)の位置の点を消去します。
CIRCLE x, y, r なし グラフィックス領域に中心(x, y)、半径rの円を描画します。
LINE a, b, x, y なし グラフィックス領域の位置(x, y)と位置(x+a, y+b)の間の線分を描画します。
PSET x, y なし グラフィックス領域の位置(x, y)に点を描画します。
PRESET x, y なし グラフィックス領域の位置(x, y)の点を消去します。
PAINT x, y なし グラフィックス領域の位置(x, y)を含む、囲まれた領域を塗りつぶします。
CLS なし なし グラフィックス領域を消去します。
+ x, yx + y 加算
- x, yx - y 減算
* x, yx * y 乗算
/ x, yx / y 除算
POW x, yx の y 乗 累乗
MINUS x-x 符号を変える
= x, yx = y x と y が等しいとき 1、そうではないとき 0
< x, yx < y x が y より小さいとき 1、そうではないとき 0
> x, yx > y x が y より大きいとき 1、そうではないとき 0
AND x, yx かつ y x と y がどちらとも真のとき 1、そうではないとき 0
OR x, yx または y x と y のどちらかが真のとき 1、そうではないとき 0
NOT xx ではない x が偽 1、そうではないとき 0
SIN xsin(x) 正弦関数
COS xcos(x) 余弦関数
TAN xtan(x) 正接関数
SINH xsinh(x) 双曲線正弦関数
COSH xcosh(x) 双曲線余弦関数
TANH xtanh(x) 双曲線正接関数
ASIN xasin(x) 逆正弦関数
ACOS xacos(x) 逆余弦関数
ATAN xatan(x) 逆正接関数
ASINH xasinh(x) 逆双曲線正弦関数
ACOSH xacosh(x) 逆双曲線余弦関数
ATANH xatanh(x) 逆双曲線正接関数
EXP xexp(x) 指数関数
LOG xlog(x) 自然対数関数
LOG10xlog10(x) 底 10 の対数関数
LOG2 xlog2(x) 底 2 の対数関数
SQRT xsqrt(x) 平方根
CBRT xcbrt(x) 立方根
ABS xabs(x) 絶対値
SIGN xsign(x) 符号を示す数値(正のとき1、0のとき0、負のとき-1)
FLOOR xfloor(x) 指定した数以下の数のうち、最大の整数値
CEILING xceiling(x) 指定した数以上の数のうち、最小の整数値
ROUND xround(x) 最も近い整数
TRUNCATE xtruncate(x) 整数部(0 に向かって最も近い整数)
RANDOM なしrandom(x) 0 以上 1 未満のランダムな浮動小数点数を発生。
E なしe 自然対数の底
PI なしπ円周率
GWIDTH なし説明を参照 グラフィックス領域の横のピクセル数
GHEIGHT なし説明を参照 グラフィックス領域の縦のピクセル数

文献

FORTHへの招待 (ソフトウェア工学ライブラリ), ハリー カッツァン (著), 池野 信一 (監訳). 近代科学社 (1982/7/1)
FORTH入門 (I/O BOOKS), レオ・ブロディー (著), 原 道宏 (翻訳), 工学社 (1984/1/1)
Microsoft Quick BASIC Ver.4.2ダイジェストガイド, SE編集部 (編集), 翔泳社 (1989/2/1)
Quick BASICビギナーズ・ガイド―構造化プログラミングとデータ構造がわかる (HBJ integrated libraries), 堀内 征治 (著), 鈴木 宏 (著), 堀内 泰輔 (著), HBJ出版局 (1989/4/1)
2022年10月2日 Ver.1.00