语言真的依赖于图书馆吗?

我一直想知道如何从编程语言到其库来管理依赖项。 以C#为例。 当我开始学习计算时,我会假设(错误的是结果)语言本身是独立于最终可用的类库而设计的。 也就是说,首先定义语言关键字集(例如forclassthrow )加上语法和语义,并且可以单独开发可以从该语言使用的库。 我曾经认为,这些库中的特定类不应该对语言的设计产生任何影响。

但这不起作用,或者不是一直都行不通。 考虑throw 。 C#编译器确保throw的表达式解析为exception类型。 Exception是库中的一个类,因此它根本不应该是特殊的。 除了C#编译器为其指定特殊语义外,它将与其他任何类一样。 这是非常好的,但我的结论是语言的设计确实取决于类库中特定元素的存在和行为。

另外,我想知道如何管理这种依赖。 如果我要设计一种新的编程语言,我会用什么技术将throw的语义映射到exception的特定类?

所以我的问题是两个:

  • 我是否认为语言设计与其基类库紧密耦合?
  • 如何在编译器和运行时内管理这些依赖项? 使用了什么技术?

谢谢。

编辑。 感谢那些指出我的第二个问题非常含糊的人。 我同意。 我想要学习的是编译器存储的所需类型的引用。 例如,它是否通过某种唯一ID找到类型? 发布新版本的编译器或类库时会发生什么? 我知道这仍然很模糊,我不期待一个精确的,单段的答案; 相反,欢迎指向文学或博客文章。

我想要学习的是编译器存储的所需类型的引用。 例如,它是否通过某种唯一ID找到类型?

显然,C#编译器在源代码和元数据中维护一个可用的所有类型的内部数据库; 这就是编译器被称为“编译器”的原因 – 它编译有关源和库的数据集合

例如,当C#编译器需要检查抛出的表达式是从System.Exception派生还是与System.Exception相同时,它假装在System上执行全局命名空间查找,然后在Exception查找,查找类,以及然后将得到的类信息与为表达式推导出的类型进行比较。

编译器团队使用这种技术,因为无论我们是编译源代码还是System.Exception都在元数据中,或者我们正在编译mscorlib本身并且System.Exception在源代码中,它就会起作用。

当然,作为一种性能优化,编译器实际上有一个“已知类型”列表,并提前填充该列表,这样它就不必每次都要花费很多时间进行查询。 您可以想象,您必须查找内置类型的次数非常多 。 填充列表后,可以从列表中读取System.Exception的类型信息,而无需进行查找。

发布新版本的编译器或类库时会发生什么?

会发生什么:一大堆开发人员,测试人员,经理,设计人员,编写人员和教育工作者聚在一起,花费几百万工时,确保编译器和类库在发布之前都能正常工作。

这个问题再次是模糊不清的。 新的编译器发布会发生什么? 很多工作 ,这就是必须要发生的事情。

我知道这仍然很模糊,我不期待一个精确的,单段的答案; 相反,欢迎指向文学或博客文章。

我写了一篇博客,其中包括C#语言及其编译器的设计。 它位于http://ericlippert.com 。

我会假设(可能是错误的)语言本身是独立于最终可用的类库而设计的。

在C#的情况下,你的假设是完全错误的。 C#1.0,​​CLR 1.0和.NET Framework 1.0都是一起设计的。 随着语言,运行时和框架的发展,每个人的设计人员密切合作,以确保分配正确的资源,以便每个人都能按时发布新function。

我不明白你完全错误的假设来自哪里; 这听起来像是编写高级语言的低效方式,也是错过最后期限的好方法。

我可以看到编写像C这样的语言,这对于汇编程序来说基本上是一种更令人愉快的语法,没有库。 但是如果没有那个人和你在房间里设计Task ,你会怎么写async-await ? 这似乎是一种令人沮丧的运动。

我是否认为语言设计与其基类库紧密耦合?

在C#的情况下,是的,绝对的。 为了正常工作,C#语言假定有几十种类型可用且已记录。

我曾经花了一个非常令人沮丧的时间与一个开发人员在一个foreach循环中遇到一些完全疯狂的问题,然后才发现他编写了自己的IEnumerable ,其方法与真正的IEnumerable略有不同 。 解决他的问题:不要那样做。

如何在编译器和运行时内管理这些依赖项?

我不知道如何开始回答这个不可思议的模糊问题。

所有(实用的)编程语言都具有最少数量的所需function。 对于现代“OO”语言,这还包括最少数量的所需类型。

如果语言规范中需要该类型,那么它是必需的 – 无论它是如何打包的。

相反, 并非所有 BCL都需要具有有效的C#实现。 这是因为并非所有BCL类型都是语言规范所要求的。 例如,需要System.Exception (参见#16.2)和NullReferenceException ,但实现C#语言不需要FileNotFoundException

请注意,即使规范提供了基类型的最小定义(例如System.String ),它也不会定义常用的方法(例如String.Replace )。 也就是说,几乎所有的BCL都超出了语言规范1的范围。


..但我的结论是语言的设计确实取决于类库中特定元素的存在和行为。

我完全同意,并在上面列出了示例(以及此类定义的限制)。

..如果我要设计一种新的编程语言,我会用什么技术将“throw”的语义映射到特殊的“Exception”类?

我不会主要看C#规范,而是看看公共语言基础结构规范。 出于实际原因,这种新语言应该设计为与现有的CLI / CLR语言互操作,但不一定需要“成为C#”。

1 CLI(和相关参考) 确实定义了最小BCL的要求。 因此,如果认为有效的C#实现必须符合(或可能采用)CLI,那么还有许多其他类型要考虑,而C#规范本身没有提到这些类型。


不幸的是,我对第二个(也是更有趣的)问题没有足够的了解。

我的印象是

在C#和Ada等语言中

应用源代码是可移植的

标准库源代码不可移植

编译器/实现