[目次へもどる] [前へ] [次へ]

スタック指向

逆ポーランド記法

"helloworld.ps"ですでに気づかれた方もいらっしゃると思いますが,Postscript は逆ポーランド記法で書かれます.何が逆なのかといえば,たとえば,C言語では "helloworld.ps"の11行目のような事は,
printf("Hello World");
というように「命令→その対象」といったような順番で記述されますが, Postscriptでは
(Hello World!) show
というように「対象→命令」といった順番で書かれます.このような記法の場合 スタックというものを使うと効率的に処理でき,Postscriptもスタックを使って います.

オペランドスタック

Postscriptではオペランドはオペランドスタックに積まれていきます. オペランドとは命令の対象物のことで,"3+9"の場合,"+"オペレータで "3"と"9"がオペランドです."helloworld.ps"の例では9行目の"/Helvetica" と"60",10行目の"100"と"100",11行目の"(Hello World!)"がオペランドです. ですから,"/Msaka 100 200"というようにオペランドを記述した 場合,オペランドスタックには上から順に,
200
100
/Msaka
といった具合に積み重ねられ,さらに"300 (takeshi)"というオペランドの記述 を追加すると,オペランドスタックは
(takeshi)
300
200
100
/Msaka
というような状態になります.そしてオペレータ(実行可能なオブジェクト) はこのスタックの上から順にオペランドを取得していきます. たとえば,このようなオペランドスタックの状態のとき,"show"オペレータを 実行すると,"show"はオペランドスタックの一番上の"(takeshi)"を引っ張り出して その文字列を紙に描くので,オペランドスタックは次のような状態になります.
300
200
100
/Msaka

対話モードで確認

では,先ほどのオペランドのやりとりを,Postscriptインタプリタを 対話モードで起動して確認します.ここではghostscriptを使います. 対話モードで起動すると,
Aladdin Ghostscript 5.10 (1997-11-23)
Copyright (C) 1997 Aladdin Enterprises,..<略>
This software comes with NO WARRANTY: ..<略>
Loading Kanji fonts... done.
Loading NimbusRomNo9L-Regu font from ..<略> done.
Loading NimbusSanL-Regu font from ..<略> done.
GS>
と表示されて,"GS>"といったプロンプトが表示されます. 今回は文字列を作画したいので,まず始めに、
GS>/Helvetica findfont 60 scalefont setfont
GS>100 100 moveto
と入力して下さい.(今は怪しいおまじないと思ってください) 次にオペランドを入力します.
GS>/Msaka 100 200
GS<3>
すると,プロンプトに現在,オペランドスタックに積まれている オペランドの数が表示されます.次に,オペランドスタックの中身を 確認してみます."pstack"というオペレータはオペランドスタックの中身を 上から順にすべてを標準出力に吐き出します.(作画はしない)この時, オペランドスタックの中身は保持されます.
GS<3>pstack
200
100
/Msaka
GS<3>
そして,オペランドを追加して,また中身を確認すると,
GS<3>300 (takeshi)
GS<5>pstack
(takeshi)
300
200
100
/Msaka
GS<5>
最後に,"show"でオペランドスタックの一番上を作画し,中身を確認すると
GS<5>show
GS<4>pstack
300
200
100
/Msaka
GS<4>
のように,オペランドスタックの一番上の"(takeshi)"が取り除かれ, "takeshi"という文字列が作画されます.終了する時は,
GS<4>quit
です.

オペランドとオペレータの順序?

"helloworld.ps"では(x,y)=(100,100)に移動して"Hello World!"を作画する時,
100 100 moveto (Hello World!) show
と記述しました."moveto"はオペランドスタックの1番上をy座標,その次をx座標 として引っ張り出して,その座標にペンを移動するオペレータです. 先ほどのスタックの概念によれば,この記述を
(Hello World!) 100 100 moveto show
と記述しても同じ結果になります.(よく考えれば分かるはずです)

スタックを操るオペレータ

スタックを操る代用的なオペレータを紹介します.

add

スタックの二番目に一番上の値を加算します
GS<2>pstack
200
100
GS<2>add pstack
300
GS<1>

sub

スタックの二番目から一番上の値を減算します
GS<2>pstack
200
100
GS<2>sub pstack
-100
GS<1>

mul

スタックの二番目に一番上の値を乗算します
GS<2>pstack
200
100
GS<2>mul pstack
20000
GS<1>

div

スタックの二番目から一番上の値を除算します
GS<2>pstack
200
100
GS<2>div pstack
0.5
GS<1>

dup

スタックの一番上を複製し,その上に積みます.
GS<2>pstack
200
100
GS<2>dup pstack
200
200
100
GS<3>

pop

スタックの一番上を捨てます.
GS<2>pstack
200
100
GS<2>pop pstack
100
GS<1>

exch

スタックの一番上と二番目を交換します.
GS<2>pstack
200
100
GS<2>exch pstack
100
200
GS<2>

copy

スタックの一番上の数を使って,二番目からその数の分だけ複製し, スタックの上に積み上げます.
GS<5>pstack
2
400
300
200
100
GS<5>copy pstack
400
300
400
300
200
100
GS<6>

index

スタックの一番上の数を使って,その数で指定される値を複製し, スタックの上に積み上げます.ただし,スタックの2番目(次の例では400)が"0", 3番目(例では300)が"1",4番目(例では200)が"2"・・・というように指定される.
GS<5>pstack
2
400
300
200
100
GS<5>index pstack
200
400
300
200
100
GS<5>

roll

スタックの一番上の数で示される数の回数だけ,二番目の数で示される数 の個数(3番目から数えて)のオブジェクトを,スタックの上方向に回転させる. 回数が負値の時は逆に回転する.
GS<6>pstack
1
3
400
300
200
100
GS<6>roll pstack           %上から3個のオブジェクトを1回転する
300
200
400
100
GS<4>3 2 roll pstack       %上から3個のオブジェクトを2回転する
400
300
200
100
GS<4>                      %結局元に戻る(3個3回転)

[目次へもどる] [前へ] [次へ]