スパゲッティ
スタック(spaghetti stack)は、別名カクタス
スタック(cactus stack)、サグアロ
スタック(saguaro stack)、イントゥリー(in-tree)とも呼ばれる、特殊なN分木構造です。この
データ構造の特徴は、子ノードが親ノードへのポインタを持つ一方で、親ノードは子ノードへのポインタを持たない点にあります。この構造により、ノードのリストを葉から親へと辿る際に、連結リストの
スタックのように動作します。
通常の連結リストとは異なり、スパゲッティ
スタックでは各ノードは唯一の親ノードへのポインタのみを持ちます。親ノードは他の子ノードに関する情報を保持しないため、子ノードから親ノードへの辿り方は一意に定まります。これにより、スパゲッティ
スタックは、実行中に動的にレコードがプッシュ・ポップされるものの、ポップされたレコードが後で利用される状況で特に有用です。
コンパイラにおける利用例
コンパイラは、ブロックスコープを表現するためにスパゲッティ
スタックを利用します。例えば、
C言語のような言語では、新しいブロックスコープが開かれるたびに、そのスコープに対応するシンボルテーブルがスパゲッティ
スタックにプッシュされます。ブロックスコープが閉じられると、対応するシンボルテーブルは
スタックからポップされますが、破棄されるのではなく保持されます。これにより、コンパイラは
抽象構文木を翻訳する際、特定の式が含まれる環境におけるシンボルテーブルを簡単に参照し、識別子への参照を解決することができます。
例えば、変数Xへの参照があった場合、コンパイラはまず最も内側の静的スコープを表す葉のシンボルテーブルを検索し、見つからなければ親のシンボルテーブルを順に検索していきます。これにより、変数のスコープを正しく管理することができます。
スパゲッティ
スタックは、特に
継続をサポートする
プログラミング言語の実装において、重要な役割を果たします。
継続とは、プログラムの実行状態を保存し、後でその状態から実行を再開する機能です。
継続をサポートする場合、関数からリターンする際に、その関数のローカル変数を破棄することはできません。なぜなら、保存された
継続が後でその関数に再び入る可能性があり、その際には完全な状態の変数と過去の
スタックが必要になるからです。
この問題を解決するために、
スタックフレームはスパゲッティ
スタック内で動的にメモリ確保されます。そして、その
継続が不要になった場合、
ガベージコレクションによってメモリが解放されるまで保持されます。この構造は、上向きおよび下向きのファンアグメント問題(関数が定義された環境とは異なる環境で呼び出されることによる問題)を解決し、一級レキシカル
クロージャ(関数が定義された環境を保持する
クロージャ)を容易に実装することができます。
SchemeやStandard ML of New Jerseyのような一級
継続を持つ言語
Smalltalkのように実行時に実行
スタックを検査・修正できる言語
Felix
Cilk
スパゲッティ
スタックと類似の
データ構造は、素集合森に見られます。素集合
データ構造では、要素をグループ化し、各グループを木構造で表現します。この木構造もまた、子ノードから親ノードへのポインタを持ち、スパゲッティ
スタックと同様の性質を持っています。
その他の関連事項
永続
データ構造:スパゲッティ
スタックは、過去の状態を保持する必要があるため、永続
データ構造との関連性があります。
バロースB5000:初期のコンピュータシステムであるバロースB5000も、
スタックベースのアーキテクチャを採用しており、スパゲッティ
スタックの概念と関連付けられることがあります。