2

(私はさらに別の質問に戻ってきました:-))

次の PostScript コードがあるとします。

/riverside { 5 pop } def
/star { 6 pop 2 {riverside} repeat } def
star

ネストされたプロシージャをどのように処理する必要があるのか​​ 疑問に思っています。(私は自分のインタープリターを作成しています)。 star プロシージャを実行すると、途中で nameObjec(riverside) が見つかり、riverside プロシージャの値を含む実行可能配列に置き換えて実行します。繰り返し演算子を実行すると、スタックにアイテムが 1 つしか残っていないため、インタープリターがクラッシュします。

既に実行可能配列 (=prodecure) にいるときに実際に実行可能配列 (=procedure) を直接実行する必要がありますか、それとも実行可能配列 (=procedures) を常に (operand?/execution?) スタックにプッシュする必要がありますか? または別のオペレーターによってのみ実行されますか? この川岸は何回処刑されるべきか?(2回か3回?)2回かな?

参考までに: これは、3 行目でstarを実行したときの状況です(エラーを参照)。

% begin execute 3rd line (star)
% OP = operand stack
% EX = execution stack    

% handle 6
OP: 6
EX: star

% handle pop (removes 6 from OP)
OP: -
EX: star

% handle 2
OP: 2
EX: star

% set the riverside executable array on the EX, execute the values
OP: 2
EX: star riverside

% repeat operator:
CRASH, only one item on the OP left, but repeat operator requires 2 operands.
OP: 5
EX: 

% end

この問題はやや複雑/紛らわしいので、光を当ててください:-)

更新: 別のコード サンプルは次のようになります。

/starside
{ 72 0 lineto
currentpoint translate
-144 rotate } def

/star
{ moveto
currentpoint translate
4 {starside} repeat
closepath
gsave
.5 setgray fill
grestore
stroke } def

200 200 star

showpage

インタプリタが/star { moveto をトークン化するとき ...ネストされた{starside}に遭遇した場合、それはどのように扱われますか? (+ {starside}だけでなく{starside 5 2 mul pop}があったとしたら?)

4

1 に答える 1

3

PLRM のセクション 3.5.3 を見る必要があると思います。これは単純な実行可能配列を扱っていますが、概念は同じです。トークン スキャナーが「{」に遭遇すると、実行可能な配列の構築を開始します。一致する '}' トークンに到達するまで、スキャナは検出したものをオペランド スタックに格納するだけです。一致する '{' に遭遇すると、オブジェクトは実行可能な配列に変換されます (そしてオペランド スタックに格納されます)。

スキャナが実行可能ファイル名を検出した場合、スキャナはその名前をオペランド スタックに格納します。名前を実行することはなく、関連付けられたオブジェクトを取得するために検索を実行することもありません。

したがって、例で「}」を実行する直前に、オペランド スタックには 2 つのオブジェクト、「{」開始配列、および実行可能ファイル名 riverside が含まれます。'}' に遭遇すると、スキャナーは実際の実行可能配列を作成し、それをオペランド スタックに格納します。(注、実装の詳細はここで異なります)

したがって、'repeat' の実行の直前に、スタック上に 2 つのオブジェクト (カウンターと、単一の実行可能ファイル名を含む実行可能配列) が存在することになります。

名前を含む実行可能配列が実行されるまで、名前を調べません。

これにより、より明確になる可能性があります。

%!
/test {(This is my initial string\n) print} def
2 {test} repeat
2 {test} /test {(This is my second string\n) print} def repeat

実行可能ファイル名 'test' を含む実行可能配列を作成した後で'test' を再定義しましたが、実行では test の後の定義が使用されていることに注意してください。ご覧のとおり、名前の検索を早すぎないことが非常に重要です。

于 2013-05-08T12:24:03.317 に答える