寿命

この節では、パステルステッチのインタープリターがリソースの寿命を管理する方法を規定する。

識別子の生成と保持

寿命の管理は無名ベクトルを通じて行われる。識別子 (identifier) は無名ベクトルの同義語である。この文書では、無名ベクトルの、寿命管理の対象としての機能に着目するとき、識別子という用語を用いる。

新たな識別子を生成する (create) ことができる。識別子の生成は明示的に行うこともできるし、暗黙的に行われる場合もある。新たに生成された識別子は live 状態である。

識別子は別の識別子を保持する (hold) ことができる。識別子が別の識別子を保持しているとき、その関係を取りやめることを解放 (free) という。

暗黙のうちに生成される識別子

パステルステッチのコア言語によって暗黙のうちに生成される識別子には、以下のものがある。

静的環境が作成されたとき、静的環境識別子 (static environment identifier) とデフォルト識別子 (default identifier) が生成される。

イニシャライズ実行または本体実行を開始するとき、動的環境が作成され、同時に、動的環境識別子 (dynamic environment identifier) が生成される。このとき、新たに生成された動的環境識別子は、特にどの識別子にも保持されない。

実行位置が continuation ブロックのブロック開始文を通過すると、コンティニュエーションが作成される。コンティニュエーションは内部に動的環境を含んでいるので、コンティニュエーションと同時に動的環境が作成される。このとき、実行中の動的環境を親動的環境、新たに作成された動的環境を子動的環境という。コンティニュエーションが作成されるとき、子動的環境の動的環境識別子が生成される。このとき、子動的環境の動的環境識別子はデフォルト識別子に保持される。また、親動的環境の動的環境識別子が保持している識別子を、子の動的環境識別子も保持する。

対照的に、コンティニュエーションを実行するときは、新たな識別子が生成され、その識別子が新たな動的環境の識別子として使われる。このとき、コンティニュエーションの動的環境識別子が保持している識別子を、新たな動的環境識別子も保持する。新たに生成された動的環境識別子は、特にどの識別子にも保持されない。

終端コンティニュエーションは動的環境識別子を持たない。

引数解決を開始するとき、識別子が生成される。この識別子を引数解決識別子 (argument resolution identifier) という。引数解決識別子は動的環境識別子に保持される。引数解決識別子は、引数解決の終端要因が手続きであれば、そのままコンテキスト識別子として使用される。手続きが終了したとき、動的環境識別子はコンテキスト識別子を解放する。引数解決の終端要因が手続きでなければ、引数解決が終了した時点で、動的環境識別子がコンテキスト識別子を解放する。

明示寿命カプセルの実体が生成されたとき、識別子が生成される。これをカプセル識別子 (capsule identifier) という。特に断りがない限り、新たに生成されたカプセル識別子は、デフォルト識別子に保持される。

識別子の削除プロセス

インタープリターが動作しているとき、何らかのタイミングで、識別子の削除プロセス (identifier deletion process) が開始される。識別子の削除プロセスを実行しているとき、重複して識別子の削除プロセスが開始されることはない。識別子の削除プロセスが終了すると、インタープリターは通常の動作に戻る。

sweep isolated identifiersmain プリミティブ演算と sweep_isolated_identifiers API は、識別子の削除プロセスを明示的に開始する。ただし、実際に識別子の削除プロセスを開始するタイミングは実装により異なる。

識別子の削除プロセスは以下の手順で行われる。

  1. 孤立した識別子を検出する。孤立した識別子は isolated 状態に設定される。
  2. isolated 状態であるすべての識別子について、登録されているデストラクターを実行する。
  3. isolated 状態である識別子がカプセル識別子であるとき、その明示寿命カプセルの実体を削除する。
  4. isolated 状態である識別子と垂直でないアドレスを持つセルを削除する。
  5. isolated 状態である識別子を deleted 状態に変更する。

識別子のうち、以下のものは自立した識別子 (independent identifier) である。

自立した識別子は到達可能な識別子 (reachable identifier) でもある。到達可能な識別子に保持されている識別子は、到達可能な識別子である。到達可能でない識別子は、孤立した識別子 (isolated identifier) である。

デストラクター

識別子の削除プロセスで実行されるコンティニュエーションをデストラクター (destructor) という。

デストラクターを登録するには register specific destructormain プリミティブ演算を用いる。このプリミティブ演算は destructor 引数と to 引数を取る。これらの引数は省略できない。destructor 引数はコンティニュエーション、to 引数は識別子である必要がある。to 引数で指定された識別子が isolated 状態であるとき、destructor 引数で指定されたコンティニュエーションが実行される。

複数のデストラクターが有効であるとき、それらはすべて実行される。どのような順序で実行されるかは予測できない。

デストラクターの実体はコンティニュエーションである。デストラクターが実行されるとき、削除された識別子が main コンティニュエーション引数に渡される。また、come from コンティニュエーション引数には終端コンティニュエーションが渡される。デストラクターは、終端要因が終端コンティニュエーションである引数解決で終了する必要がある。

識別子を操作するプリミティブ演算

識別子を操作するプリミティブ演算には以下のものがある。

gismomain プリミティブ演算は引数を取らない。このプリミティブ演算は新たな識別子を生成する。新たな識別子はデフォルト識別子に保持される。戻り値は新たな識別子である。

hold additionallymain プリミティブ演算は引数 parentchild を取る。これらの引数は識別子である必要がある。このプリミティブ演算を実行すると、parent 引数の識別子が child 引数の識別子を保持する。すでに parent 引数の識別子が child 引数の識別子を保持している場合は、何も変化がない。

hold explicitlymain プリミティブ演算は引数 parentchild を取る。これらの引数は識別子である必要がある。このプリミティブ演算を実行すると、parent 引数の識別子が child 引数の識別子を保持する。また、デフォルト識別子が child 引数の識別子を保持しているならば、デフォルト識別子が child 引数の識別子を解放する。すでに parent 引数の識別子が child 引数の識別子を保持している、なおかつ、デフォルト識別子が child 引数の識別子を保持していない場合は、何も変化がない。parent 引数の値がデフォルト識別子そのものである場合の動作は実装により異なる。

freemain プリミティブ演算は引数 parentchild を取る。これらの引数は識別子である必要がある。このプリミティブ演算を実行すると、parent 引数の識別子が child 引数の識別子を解放する。parent 引数の識別子が child 引数の識別子を保持していない場合には、何も変化がない。

holdsmain プリミティブ演算は main 引数を取る。この引数は識別子である必要がある。このプリミティブ演算を実行すると、main 引数で指定された識別子が保持している識別子の集合を返す。

is held bymain プリミティブ演算は main 引数を取る。この引数は識別子である必要がある。このプリミティブ演算を実行すると、main 引数で指定された識別子を保持している識別子の集合を返す。

get static environment identifiermain プリミティブ演算は引数を取らない。このプリミティブ演算の戻り値は静的環境識別子である。

get default identifiermain プリミティブ演算は引数を取らない。このプリミティブ演算の戻り値はデフォルト識別子である。

get dynamic environment identifiermain プリミティブ演算は main 引数を取る。この引数は省略可能であり、省略しないならばコンティニュエーションである必要がある。main 引数がコンティニュエーションならば、そのコンティニュエーションの動的環境識別子を返す。main 引数を省略すると、実行中の動的環境の動的環境識別子を返す。

get independent identifiersmain プリミティブ演算は引数を取らない。このプリミティブ演算の戻り値は、自立した識別子の集合である。

get identifier statusmain プリミティブ演算は main 引数を取る。この引数は識別子である必要がある。このプリミティブ演算を実行すると、main 引数で指定された識別子の状態を返す。戻り値は livemain, isolatedmain, deletedmain のいずれかの有名ベクトルである。

互換性についての注意 過去の言語仕様では、識別子を取る引数は省略可能であり、省略した場合は静的環境識別子を意味していた。現在の言語仕様では、上記のプリミティブ演算の引数はすべて (get dynamic environment identifier プリミティブ演算を除いて) 省略不可となった。これにより、既存のプログラムの修正が必要になる場合がある。

互換性についての注意 hold プリミティブ演算とfree all プリミティブ演算は廃止された。また、get static environment anonymous vector プリミティブ演算と get dynamic environment anonymous vector プリミティブ演算は名前が変更された。実装によっては、これらのプリミティブ演算を引き続き使用できる。

これらのプリミティブ演算で、上記の条件を満たさない引数を与えた場合の動作は、実装により異なる。

静的環境のファイナライズ

静的環境のファイナライズは、ホスト言語が finalize API を通じてそれを要求したときに実行される。静的環境のファイナライズは、静的環境に属するすべての識別子が孤立しているものとして、識別子の削除プロセスを実行する。さらに、デストラクターを実行する過程で識別子が生成されたならば、静的環境のファイナライズを反復する。