Я вивчаю методи впровадження мов програмування, і нещодавно натрапив на спагеті, які нібито добре підходять для моделі стилю продовження передачі (враховуючи їх використання, наприклад, у Scheme та SML / NJ ). Для цього просто розглянемо лише однопотокові процеси для цього питання.
Однак мене трохи бентежить діаграма у Вікіпедії (також зустрічається в інших місцях ). Зокрема, я не розумію, як може виникнути така ситуація. Я можу лише уявити, що сірі гілки недоступні і їх слід збирати сміття. З іншого боку, з моїм невиразним розумінням того, як реалізувати CPS за допомогою стег-спагетті, я не уявляю, як ви могли коли-небудь отримати цикл у цій структурі. Я мушу зробити висновок, що, а не «дерево батьків-вказівників», це насправді спрямований ациклічний графік із стільки ж джерел сміття, скільки є ниток, і стільки ж раковин, що є (потенційних) «точок виходу».
Але моє розуміння цієї реалізації є досить розпливчастим, тому, мабуть, мені щось не вистачає. Я сподіваюся, що хтось може просвітити мене тут на "стеках викликів спагетті", під якими я маю на увазі структуру даних, що використовується в Scheme та / або SML / NJ для реалізації процесів на основі CPS.
Враховуючи такий стек викликів спагетті:
[exit point] <-- ... <-- [frame A] <-- [frame B (active)] ^ `---- [frame C]
Наскільки я розумію, будь-який контроль потоку з B або розкручує стек, переходячи до батьківського (A стає активним, недоступний B зараз сміттям), або замінюючи активний кадр підграфом, підключений лише за допомогою посилань, що містяться в B або посиланнях до нових кадрів. Виконання не може перетікати до кадру C, що означає, що кадр C є сміттям.
Замість попередньої ситуації, я думаю, що може виникнути така ситуація, що не має сміття:
[exit point] <-- ... <-- [frame W] <-- [frame X] <-- [frame Z (active)] ^ | `---- [frame Y] <---´
Наприклад, я можу уявити, що кадр Z належить до якоїсь функції прийняття рішення, яка або продовжується кадром X, або кадром Y (який з них повернеться до W). Це означає, що стеки викликів спагетті не є "батьківськими деревами вказівників ".
Однак я не можу уявити жодної ситуації, коли цикл може бути побудований. Візьмемо, наприклад, таку ситуацію:
[exit point] <-- ... <-- [frame P] --> [frame Q (active)] ^ | | v `---- [frame R]
Я знаю, що рекурсивні прив’язки - річ, але я дуже сумніваюся, що це розумно. Якщо Q повертаються до R, кадр Q "витрачається". Якщо R повернеться до P, а P не може просто повернутися до Q, оскільки його потрібно спочатку повторно реалізувати. Таким чином, петлі викликають непослідовні стани. (Якщо, звичайно, я неправильно розумію мету цієї структури даних, і ви використовуєте лише вузли в ній як шаблон для вашого поточного кадру.)
З цих спостережень я маю зробити висновок, що стек для виклику спагетті (без сміття) - це насправді DAG. Це правильно? Або я не розумію цілі цієї структури даних?
Оновлення:
Я проглянув копію наступного документу:
EA Hauck і BA Dent. 1968. Штабельний механізм Берроуза B6500 / B7500. У матеріалах 30 квітня - 2 травня 1968 року відбулася весняна спільна комп'ютерна конференція (AFIPS '68 (Весна)). ACM, Нью-Йорк, Нью-Йорк, США, 245-251. DOI = http://dx.doi.org/10.1145/1468075.1468111
Цей документ, схоже, визначає систему стека Suguaro. Як виявляється, ця система стека Suguaro - це традиційний стек викликів, який дозволяє безлічі "завдань" проходити через кадри частково спільного стека; це абсолютно не пов'язане з продовженням.
Наступний документ (і його супровідний документ у 1996 році), очевидно, пояснює, що відбувається в компіляторі SML / NJ:
Чжун Шао та Ендрю В. Апель. 2000. Ефективне та безпечне перетворення закритого простору. ACM Trans. Програма. Ланг. Сист. 22, 1 (січень 2000 р.), 129-161. DOI = http://dx.doi.org/10.1145/345099.345125
Думаю, я повинен прочитати цей документ ( копію на веб-сайті автора ), перш ніж займатись цим питанням. Концепція "Безпечно пов'язані закриття" дуже схожа на систему Suguaro Stack, оскільки вона завжди дуже неглибока і призначена лише для обміну вільними змінними:
Наш новий алгоритм перетворення-закриття використовує безпечно пов’язані закриття (3-й стовпець на рисунку 1), які містять лише змінні, фактично необхідні у функції, але уникають копіювання закриття шляхом групування змінних з однаковим терміном експлуатації у запис, який можна поділити. [...] На відміну від пов'язаних закриттів, рівень гніздування безпечно пов'язаних закриттів ніколи не перевищує більше двох (один шар для самого закриття; інший для записів різного часу життя), тому вони все ще користуються дуже швидким змінним часом доступу.
У документі також прямо зазначається, що він не використовує "жодного стеку виконання":
Натомість ми розглядаємо всі записи активації як закриття для функцій продовження та розподіляємо їх у регістрах у купі.
Я думаю, що я неправильно зрозумів та / або неправильно прочитав статтю у Вікіпедії, оскільки стеки спагетті не використовуються для контролю потоку. Однак, уважно прочитавши статті Аппеля і Шао, я, можливо, міг би повторно поставити питання стосовно графіка закритості, а не до "стека виклику спагетті" (що, очевидно, не є річчю).