Mar*_*arc 5 compiler-construction closures functional-programming sml smlnj
将函数式程序编译为机器语言时,编译器必须选择如何实现闭包。在以下示例(方案语法)中,该函数f返回(lambda (y) (+ x y))其机器表示(其闭包)必须包含一个代码指针和一个值的过程x。
(lambda (f x)
(lambda (y) (+ x y))
Run Code Online (Sandbox Code Playgroud)
闭包转换是为这种机器表示选择布局的过程。两种典型的策略是链表或平面闭包。虽然平面闭包可能涉及额外的值复制,但朴素链表通常对空间不安全(变量在最后一次使用后保持活动状态)。
Keep、Hearn 和 Dybvig 在他们的论文Optimizing Closures in O(0) time 中描述了一种优化平坦闭包策略的算法。当编译策略是基于堆栈的时,该算法给出了很好的结果。对于在堆上分配激活记录的基于 CPS 的编译器(请参阅Appel 的持续编译),Keep 等人的算法。似乎没有给出最佳结果。
另一方面,Appel 和 Shao 在他们的论文Efficient and Safe-for-Space Closure Conversion 中提出了一种非常复杂的闭包转换算法,其中闭包被实现为平面闭包和纯链表之间的某种东西,这是安全的空间和它适用于使用 CPS 并显式传递延续的编译器。本文中的例子表明,该算法给出了非常好的结果。
鉴于 Appel 和 Shao 的论文已有大约 20 年的历史,我想知道在 CPS 中为函数式语言执行闭包转换时它是否仍然是最先进的。
在他们的论文中,他们提到该算法已在 SML/NJ (1.03z) 版本中成功实现;不过,我还没有成功地在当前版本的 SML/NJ 中找到该算法的实现。
该算法是否或是否在实际编译器中使用?或者是否有改进或其他已知的闭包转换算法,当在堆上分配活动记录时,它们既安全又高效(这又允许 O(1) 实现call/cc)?这些算法是否曾经实施过,或者它们的原因是否与它们的效率背道而驰?
为了允许对各种策略进行实验,如果答案包括(引用)(开源)算法的实现,或者至少包括现有的编译器,那就太好了。这也可能暗示这些算法如何在实践中证明。