【问题标题】:how can a compiler that recognizes the iterators be implemented?如何实现识别迭代器的编译器?
【发布时间】:2010-11-10 05:29:07
【问题描述】:

我使用迭代器已经有一段时间了,我喜欢它们。

但是,尽管我仔细考虑过,但我无法弄清楚“如何实现识别迭代器的编译器”。我也对此进行了研究,但找不到任何资源来解释编译器设计上下文中的情况。

详细地说,大多数关于迭代器的文章都暗示存在某种“魔法”来实现所需的行为。他们建议编译器维护一个状态机,以便跟踪执行的位置(看到最后一个“yield return”的位置)。我对启用惰性求值的 Iterators 的这个属性特别感兴趣。

对了,我知道什么是状态机,已经上过编译器设计课程,学过龙书。但显然,我无法将我所研究的内容与 csc 的“魔法”联系起来。

感谢任何知识或不同的想法。

【问题讨论】:

  • 你能再解释一下吗?例如,您认为编译器很难识别的源代码示例?
  • 还有你在说什么语言——例如“yeild”是做什么的?
  • C# 有一个“收益回报”语法。
  • 对不起,我的参考语言是c#。

标签: iterator compiler-construction yield-keyword


【解决方案1】:

它比看起来更简单。编译器可以将迭代器函数分解成单独的块;块被yield 语句分割。

状态机只需要跟踪我们当前所在的块,并在下一次调用迭代器时直接跳转到该块。我们还需要跟踪所有局部变量(当然)。

然后,我们需要考虑一些特殊情况,特别是包含yields 的循环。幸运的是,IL(但不是 C# 本身)允许 goto 跳转进入循环并恢复它们。

请注意,有一些非常复杂的边缘情况,例如C# 不允许 yieldfinally 块中,因为在 yield 上离开函数会非常困难(不可能?),然后恢复函数,执行清理,重新抛出任何异常 并且保留堆栈跟踪。

Eric Lippert 已在in-depth description 上发布了该过程。(也请阅读他链接到的文章!)

【讨论】:

    【解决方案2】:

    我会尝试的一件事是用 C# 编写一个简短的示例,对其进行编译,然后在其上使用 Reflector。我认为这个“yield return”的东西只是语法糖,所以你应该能够在反汇编器的输出中看到编译器是如何处理它的。

    但是,好吧,我对这些事情知之甚少,所以也许我完全错了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-28
      • 2017-04-06
      • 2016-01-23
      • 2011-03-12
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多