制御フロー

パステルステッチのプログラムを実行すると、まずイニシャライズ実行 (initialize execution) が行われ、それが終わると本体実行 (main execution) が行われる。本体実行では、パステルステッチのプログラムに書かれているブロックまたは文を前方 (upper side) から後方 (lower side) に向けて順に実行する。ただし、以下のブロックは、プログラムの実行位置 (execution position) が到達しても実行されない。実行位置は次のブロックまたは文まで移動する。

また、制御構文のうち引数解決ディレクティブは、プログラムの実行位置が到達しても実行されない。実行位置は次のブロックまたは文まで移動する。

統合演算形式

統合演算文のうち、演算指示子が特定の複合名と一致するものは制御構文 (control flow statement) である。また、統合演算文または統合演算式のうち、演算指示子が特定の複合名と一致するものは制御式 (control flow expression) である。

制御構文または制御式でない統合演算形式が実行されると、まず演算指定子と引数の値が計算され、続いて、引数解決 (argument resolution) が行われる。

制御式

andmain 制御式と ormain 制御式はそれぞれ left 引数と right 引数を取る。これらの引数はそれぞれ左辺と右辺に対応する。and 制御式が実行されると、まず左辺の値が計算される。左辺の値が偽 (ブーリアン型の false) であれば、右辺は計算されず、左辺の値を戻り値とする。左辺の値が真 (ブーリアン型の true、またはブーリアン型でないすべての値) であれば、右辺を計算し、右辺の値を戻り値とする。対照的に、or 制御式が実行されると、まず左辺の値が計算される。左辺の値が真であれば、右辺は計算されず、左辺の値を戻り値とする。左辺の値が偽であれば、右辺を計算し、右辺の値を戻り値とする。

ifmain 制御式は引数 if, then, else を取る。この制御式が実行されると、まず if 引数が計算される。この引数の値が真であれば then 引数、偽であれば else 引数が計算され、それぞれこれらの引数の値が戻り値となる。

互換性についての注意 過去の言語仕様では control flow and, control flow or, control flow if 制御式が規定されていた。これらの制御式は廃止された。

and thenmain 制御式と return and thenmain 制御式を総称してシーケンシャル演算 (sequential operation) という。シーケンシャル演算は left 引数と right 引数を取る。これらの引数はそれぞれ左辺と右辺に対応する。シーケンシャル演算は以下の手順で実行される。

  1. 左辺を計算する。
  2. 左辺の値をシーケンシャル演算スタックにプッシュする。
  3. 右辺を計算する。
  4. シーケンシャル演算スタックをポップする。
  5. and then 制御式であれば右辺の値、return and then 制御式であれば左辺の値を戻り値とする。

シーケンシャル演算の右辺を計算する過程で、シーケンシャル演算スタックのトップの値を %main 複合名で得ることができる。

手続き

手続きを登録するには procedure ブロックを使用する。procedure ブロックのブロック開始文は main 引数を取る。この引数の値はベクトルである必要がある。procedure ブロックは手続きとベクトルを結び付ける。手続きの登録はイニシャライズ実行で行われ、本体実行では procedure ブロックは単に読み飛ばされる。procedure ブロックの内部にさらに procedure ブロックを記述することができるが、外側と内側の procedure ブロックには特に関係性は発生しない。

手続きを実行するには、統合演算形式の演算指定子に、その手続きに対応するベクトルを与える。引数解決で、終端要因が手続きであれば、その手続きが実行される。その統合演算形式の引数は、手続きの内部ではコンテキスト引数を通して取得できる。

この文書では、procedure ブロックで区分けされたコードを手続き (procedure)、手続きを実行するたびに作られるデータ構造をコンテキスト (context) として区別する。

手続きの実行中はコンテキスト引数の値を参照できる。コンテキスト引数 offsetverb は特殊なコンテキスト引数である。offset コンテキスト引数の値はコンテキスト識別子 (subroutine identifier) である。コンテキスト識別子は、手続きを実行するごとに作られる (正確には、引数解決を開始した時点で作成される) 一意な無名ベクトルである。verb コンテキスト引数の値は演算指定子である。

これらの特殊なコンテキスト引数を除いて、コンテキスト引数の値は、手続きを呼び出した統合演算形式の引数の値である。これらのいずれにも当てはまらないコンテキスト引数の値はブーリアン型の false である。

メインルーチンでは、offset コンテキスト引数の値はメインルーチンに固有の無名ベクトルである。他のコンテキスト引数の値はブーリアン型の false である。

return プリミティブ演算は main 引数の値を手続きの戻り値に設定する。他のプログラミング言語と違って、パステルステッチの return は手続きを終了せず、単に戻り値を設定するだけである。return プリミティブ演算を複数回実行した場合は、最後に実行したとき指定した値が戻り値になる。また、return プリミティブ演算を実行せずに手続きを終了した場合は、戻り値はブーリアン型の false である。

escape 制御構文は手続きを終了する。実行位置が手続きの終端に達した場合にも、同様に手続きを終了する。

手続きとコンテキストを取り扱うために、以下のようなプリミティブ演算がある。

互換性についての注意 get argumentmain プリミティブ演算は廃止された。かわりに引数パックを使用することができる。

引数パック

引数パック (argument pack) は、引数の名前と値の組をイミュータブルマップコンテナに格納したものである。このイミュータブルマップコンテナのキーは、固有名が引数の名前で、姓が argument symbol である有名ベクトルである。

get argumentsmain プリミティブ演算は main 引数を取る。この引数はコンテキスト識別子である必要がある。このプリミティブ演算は、main 引数で指定されたコンテキスト識別子を持つコンテキストの、すべてのコンテキスト引数を引数パックに格納して返す。ここで得られる引数パックは、特殊なコンテキスト引数である verboffset を含まない。

get continuation argumentsmain プリミティブ演算は引数を取らない。このプリミティブ演算は、すべてのコンティニュエーション引数を引数パックに格納して返す。ここで得られる引数パックは、特殊なコンテキスト引数である verboffset を含まない。

互換性についての注意 call with continuation argumentsmain 制御式と call with context argumentsmain 制御式は廃止された。かわりに引数パックを使用することができる。

条件分岐

条件分岐には if ブロックを使用する。if ブロックのブロック開始文の main 引数が真であれば if ブロックの内容が実行される。if ブロックのブロック開始文の main 引数がブーリアン型の false であれば、if ブロックの終端まで実行位置が移動する。

ループ

ループには loop ブロックを使用する。実行位置が loop ブロックの終端に達すると、実行位置が loop ブロックの先頭まで戻る。loop ブロックのブロック開始文は引数を取らない。

ループを抜けるには breakmain 制御構文を使用する。break 制御構文の main 引数が省略されたとき、または、その引数の値が偽であるときは、ループを抜ける。main 引数の値が真であるときは、そのまま次のブロックまたは文に進む。

インタープリターの終了

引数解決の終端要因が終端コンティニュエーションであるとき、インタープリターが終了する。このとき引数解決で使用されていた引数は、インタープリターが終了した後、ホスト言語で参照できる。イニシャライズ実行または本体実行で、実行位置がプログラムの終端に達したときも、同じようにインタープリターが終了する。

互換性についての注意 過去の言語仕様との互換性のため、halt 制御構文でインタープリターを終了することができる。この仕様は将来の言語仕様で廃止される可能性がある。

イニシャライズ実行

イニシャライズ実行では以下の処理が行われる。

これらの処理がプログラムの前方から後方に向けて順に実行される。イニシャライズ実行の過程では、すでに登録されている手続きを実行することが可能である。また、イニシャライズ実行の過程では、引数解決ディレクティブは無効である。