Skip to content

Latest commit

 

History

History
96 lines (72 loc) · 6.66 KB

File metadata and controls

96 lines (72 loc) · 6.66 KB

shell stackingの動作

shell stackingはスタックベースの言語で、1本のスタックと1つのヒープ(配列)にデータを保持し、スタックを利用して計算を行います。

データ型

スタックおよびヒープに保持されるデータは符号付きの整数です。
扱える値の範囲は処理系を実行するシェルの仕様に依存します。

データ構造

スタックとヒープがそれぞれ1つ存在します。
スタックとヒープは内部的には同じ型の実体であり、データを保持することのできる数やヒープの添え字の範囲は処理系を実行するシェルの配列変数の仕様に依存します。

スタック

LIFOの単方向スタックで、プッシュ(トップへの要素追加)とポップ(トップの要素の取り出し)を行うことができます。ポップした値はその時点でスタックから無くなります。
命令の内容で後述する通り、演算のオペランドはスタックから取り出されます。
スタックのサイズとは、スタックに保持されているポップで取り出し可能なデータの数です。
空の(サイズが0の)スタックからポップを行うと0を返し、スタックのサイズは0未満にはなりません。

ヒープ

添え字によるランダムアクセスが可能な配列です。データの読み出しを行ってもその位置のデータは保持されます。
演算に使用されることは無く、主にデータの一時的な保存に用いられます。
添え字の最小値は0で、^命令の実行時に0未満の添え字が指定されるとエラーとなります。添え字の最大値は処理系を実行するシェルの仕様に依存します。
未定義の(データを一度も書き込んでいない)添え字から読み出しを行うと、その時点でその位置のデータが0に初期化され、0を返します。

命令の内容

各命令はスタック、ヒープ、標準入出力またはプログラムの実行位置に影響を与えます。
命令は原則ソースコードに記述された順序で実行され、実行位置が移動した(ジャンプした)ときはその位置からまた記述通りの順序で実行されます。このドキュメントに「hogeの位置にジャンプする」と記載されている場合、次に実行されるのはhogeの次に記述されている命令です。

<半角アルファベット>

その文字のASCIIコードをスタックにプッシュします。例えばAを実行すると65が、aを実行すると97がプッシュされます。

<半角数字>

その数をスタックにプッシュします。例えば0を実行すると0がプッシュされます。

+ - * / %

それぞれ最初にポップした値を右オペランド、2番目にポップした値を左オペランドとして二項演算を行い、結果をスタックにプッシュします。
演算の内容は順に加算、減算、乗算、除算、剰余算です。
ただし、除算の結果は必ず整数となり、丸めの規則は処理系を実行するシェルの仕様に依存します。

< >

それぞれ最初にポップした値を右オペランド、2番目にポップした値を左オペランドとして比較を行い、結果が真なら1を、偽なら0をプッシュします。
<命令は左オペランドが右オペランド未満のときに、>命令は左オペランドが右オペランドより大きいときに真となります。

?

ポップした値が0より大きいなら1を、そうでないなら0をプッシュします。

!

ポップした値が0なら1を、そうでないなら0をプッシュします。

:

ポップした値を2回プッシュします。つまり、スタックトップを複製します。

\

2回ポップした値を逆順でプッシュします。つまり、トップの2要素を入れ替えます。

#

実行直前のスタックのサイズをプッシュします。

$

一度ポップして、その値を読み捨てます。

^

最初にポップした値を添え字として、2番目にポップした値をヒープに書き込みます。
添え字となる値が0未満だった場合、プログラムは異常終了します。

~

ポップした値を添え字としてヒープからデータを読み出し、プッシュします。

,

入力バッファが空であれば、標準入力から読み込んだ文字列を入力バッファに格納します。その後、入力バッファの1文字目の文字コードをプッシュし、入力バッファからその文字を取り除きます。
入力には空白やタブ文字を含めることができますが、改行文字を含めることはできません。
入力バッファの最大長は処理系を実行するシェルの仕様に依存します。

|

標準入力から読み込み、10進整数として解釈してその数値をプッシュします。
符号は無しまたは'-'1つで、それに続いて1文字以上の半角数字を入力しなければなりません。これに従わない入力が行われた場合は、正しい形式で入力されるまで繰り返し入力を待ち受けます。
解釈する文字列に一度数字でない文字が現れると、それ以降の文字は数字であっても無視されます。例えば"-123abc456"が入力されると、数値-123として解釈されます。

.

ポップした値をUnicodeとして解釈し、対応する文字を標準出力に出力します。改行は行いません。

_

ポップした値を10進整数として数字で出力します。改行は行いません。
0以上の値では符号無し、0未満の値では符号'-'を付けて出力されます。

[ ]

ループ命令です。
[命令実行時にポップした値が0だった場合、対応する]にジャンプします。そうでなければ何もしません。
]命令を実行すると、無条件に対応する[の1つ手前にジャンプします。つまり、]命令の次には対応する[命令が実行されます。

( )

条件分岐命令です。
(命令実行時にポップした値が0だった場合、対応する)にジャンプします。そうでなければ何もしません。
)命令自体は何も行いません。(のジャンプ先としてのみ機能します。

@

実行すると、その時点でプログラムを正常終了します。