编译中的声明捕获阶段 语言如C和C++依赖于前向声明来解决类型或函数声明中的循环依赖关系。在C#中,这不再是必需的,因为声明捕获阶段分为两个阶段;一个捕获符号名称,另一个实际执行符号声明构造

编译中的声明捕获阶段 语言如C和C++依赖于前向声明来解决类型或函数声明中的循环依赖关系。在C#中,这不再是必需的,因为声明捕获阶段分为两个阶段;一个捕获符号名称,另一个实际执行符号声明构造,c#,compilation,declaration,forward-declaration,C#,Compilation,Declaration,Forward Declaration,符号名称捕获阶段是否有标准名称?我假设声明捕获将留给传统阶段,该阶段涉及解析声明中的所有符号我认为这两个阶段称为 解析 装订 句法分析是句法分析。绑定是给标识符和名称赋予意义 C++也可以这样做。它只是被定义为“不”。对于.Net 5,Microsoft将引入Roslyn,编译器作为一种服务。for Roslyn将编译器在代码生成之前的三个步骤描述为:词法分析、语法分析和语义分析。确认了这些描述,但使用了不太精确的语言。C#编译器实际上有一个声明阶段,它在其中构建符号表。Roslyn C#编译器

符号名称捕获阶段是否有标准名称?我假设声明捕获将留给传统阶段,该阶段涉及解析声明中的所有符号

我认为这两个阶段称为

  • 解析
  • 装订
  • 句法分析是句法分析。绑定是给标识符和名称赋予意义


    C++也可以这样做。它只是被定义为“不”。

    对于.Net 5,Microsoft将引入Roslyn,编译器作为一种服务。for Roslyn将编译器在代码生成之前的三个步骤描述为:词法分析、语法分析和语义分析。确认了这些描述,但使用了不太精确的语言。

    C#编译器实际上有一个声明阶段,它在其中构建符号表。Roslyn C#编译器不是很清楚,因为不是所有的事情都是在大的扫描阶段完成的。相反,每个符号都是根据需要单独构造的。但是,仍然有一个步骤可以将语法中的类型和成员声明转换为符号。绑定阶段在逻辑上是在这之后进行的,其中对类型和成员名称的引用使用声明的符号表进行解析。

    我从Eric Lippert那里找到了这篇博文,它对我所寻找的内容给出了最好的解释:

    C语言不要求声明在之前发生 用法,这同样对用户和编译器有两个影响 作家。对用户的影响是,您不能仅仅重新编译 更改文件时更改的IL;整个大会正在进行 重新编译。幸运的是,C#编译器的速度足够快,因此 这很少是个大问题。(另一种看法是 C#中重新编译的“粒度”是项目级别的,而不是 文件级。)

    对编译器编写器的影响是我们必须有一个“两次通过” 编译器。在第一步中,我们查找声明并忽略 身体。一旦我们从声明中收集了所有信息 我们将从C++的头中得到,我们将通过第二关。 通过代码并为实体生成IL

    然后,我们做一个“声明”通行证,在那里我们对 程序中每个命名空间和类型声明的位置。在 在这一点上,我们已经完成了第一阶段的源代码; 随后的每一次传递都是在从 声明

    然后执行一个过程,验证声明的所有类型都没有 基本类型中的循环。我们需要先这样做,因为在每一个 在后续过程中,我们需要能够在没有 必须处理周期


    不,我认为声明捕获阶段发生在AST构建之后,也就是在解析阶段完成之后。害怕你的评论,我不知道你所说的声明捕获到底是什么意思。(1)和(2)之间没有关系。这样一个阶段会做什么?解析器已经将声明“捕获”到AST中。您提到的绑定阶段可以细分为子阶段、符号名称解析(不确定这是否是正确的名称)、声明捕获,最后是绑定正确(将实现连接到声明),但最后一个阶段仍在链接阶段继续。我仍然不知道“声明捕获”的作用,我在网上找不到它。也许我对这个话题了解不够。至少我可以说,在C#编译器中不需要单独的链接阶段,我相信它不存在。一旦您知道名称“xyz”所指的AST节点,您就完成了绑定(和链接)。没什么可做的了。我觉得没那么简单;以两个类声明为例,一个具有另一个类型的成员。只有先解析类名,然后将声明附加到这些名称,才能打破循环依赖关系