前段时间翻译了一篇文章 微软是如何重写 C# 编译器并使它开源的,文章讲了微软用 C# 重写 C# 编译器的坎坷路,引发了一些童鞋的思考:用 C# 编写 C# 编译器(Roslyn),那么 C# 编译器本身是由谁来编译的?C# 语言编写了 C# 编译器,而 C# 语言又是由 C# 编译器编译的,这不就是先有鸡还是先有蛋的问题吗?

虽然(博客园)文章下方评论中提出这类问题的人不多(注:除了公众号,我的技术文章一般也会隔天在博客园发布),但我相信有这类疑问的人肯定不少。这个问题提得很好,会产生这个疑问说明你是个善于思考的人,有思辨能力;如果你又恰好看到了我这篇文章,得到了你要的答案,那么这就是我写文章的意义。

看到童鞋们的评论,我并没有立即回复,因为这个问题确实不好回答。但作为 .NET 忠实的布道老者(请允许我装逼一回),我还是觉得有必要给大家解释一下。

首先,编译器 Roslyn 确实是自己编译自己,它的每个版本都是由该版本的上一个版本来编译的。那么 Roslyn 最初的第一个版本是由什么来编译的呢?

这里就要提到了个计算机科学中的一个概念:Bootstrapping Compiler,中文叫自举编译器。它的目的是实现自己编译自己。编译器为了达到自己编译自己的目的,它第一个版本必须由其它编程语言来实现,而它的第一个版本通常是非常简单和基础的版本。

很多编程语言发展成熟后都会用该语言本身来编写自己的编译器,比如 C# 和 Go 语言。

C# 编译器 Roslyn 的第一个版本是由其它语言来编译的。具体是什么语言我不确定,我觉得应该是用 C++ 写的(因为老的 C# 编译器用的是 C++),我还没查到,如果你知道,麻烦留言告诉我。

如果 Roslyn 的第一个版本是由 C++ 来编写的,那么 C++ 编译器的第一个版本又是由什么来编写的呢?如果不是 C 语言那很可能就是直接用机器语言来编写的了,机器语言是操作系统可以直接运行的指令,自然不需要编译器来翻译。

所以,但凡自举编译器是由高级语言来编写的,它的第一个版本一定是由其它语言来编写的,追溯它最初的祖先,一定是用机器语言来编写的。

2018-10-14 续

关于 C# 编译器 Roslyn 的第一个版本是用什么编译的,我在 Medium 留言问了 C# 语言负责人 Mads Torgersen:

他的回答是:

至此,文中的怀疑得到了确认。也就是说 Roslyn 最初的第一版是用老的 C# 编译器编译的(老的编译器是用 C++ 编写的),之后都是用 Roslyn 自己编译的。

用 C# 编写 C# 编译器,先有鸡还是先有蛋?的更多相关文章

  1. 编写COOL编译器

    Coursera上面有Stanford的课程“Compilers”,该课程使用“龙书”作为参考书,并有一个编程项目,完成一个完整的编译器.这个编译器支持的语言称为COOL,是一个面向对象的用于教学的语 ...

  2. Java中关于先有鸡还是先有蛋的问题----Class&Object

    在Java中,我们常常会看到一个类型:Class.并且在类似Person.class,cache.getClass()等代码中见到它的身影. 众所周知,Class是用来描述一个类的类型,而Object ...

  3. c++类模板之分文件编写问题及解决

    我们在实际项目中一般习惯头文件(.h)和源文件(.cpp)分开写,这样做的好处良多,但是如果遇到了类模板,这样可能会有一点儿问题. 我们通过一个例子来看: person.h: #pragma once ...

  4. [.NET大牛之路 006] 了解 Roslyn 编译器

    .NET大牛之路 • 王亮@精致码农 • 2021.07.09 维基百科对编译器的解释是:编译器是一种程序,它将某种编程语言编写的源代码(原始语言)转换成另一种编程语言(目标语言).编译是从源代码(通 ...

  5. Roslyn 编译器Api妙用:动态生成类并实现接口

    在上一篇文章中有讲到使用反射手写IL代码动态生成类并实现接口. 反射的妙用:C#通过反射动态生成类型继承接口并实现 有位网友推荐使用 Roslyn 去脚本化动态生成,今天这篇文章就主要讲怎么使用 Ro ...

  6. .Net 新一代编译器 Roslyn 会带来怎样的影响?

    .Net 新一代编译器 Roslyn 会带来怎样的影响? Roslyn是微软创建的一个.NET编译器平台,该项目于2014年4月3日开源. 最初 C# 语言的编译器是用 C++ 编写的,后来微软推出了 ...

  7. .Net内存泄露原因及解决办法

    .Net内存泄露原因及解决办法 1.    什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...

  8. YDKJS:作用域与闭包

    作用域与闭包 什么是作用域 编译器 理解作用域 嵌套的作用域 词法作用域 词法分析时 欺骗词法作用域 函数与块作用域 函数中的作用域 隐藏标识符于普通作用域 函数作为作用域 块作为作用域 提升 先有鸡 ...

  9. 你不知道的JS之作用域和闭包(四)(声明)提升

    原文:你不知道的js系列 先有鸡还是先有蛋? 如下代码: a = 2; var a; console.log( a ); 很多开发者可能会认为结果会输出 undefined,因为 var a 在 a ...

随机推荐

  1. [UOJ310] 黎明前的巧克力

    Sol 某比赛搬了这题. 首先选择两个不交非空子集且异或和为0的方案数,等价于选择一个异或和为0的集合,并把它分成两部分的方案数. 这显然可以DP来算,设 \(f[i][j]\) 表示前\(i\)个数 ...

  2. MySQL/MariaDB系列文章目录

    以下是本系列文章的大纲,此页博文完全原创,花费了作者本人的极大心血,如转载,请务必标明原文链接. 如果觉得文章不错,还请帮忙点下"推荐",各位的支持,能激发和鼓励我更大的写作热情. ...

  3. springboot(五)过滤器和拦截器

    前言 过滤器和拦截器二者都是AOP编程思想的提现,都能实现诸如权限检查.日志记录等.二者有一定的相似之处,不同的地方在于: Filter是servlet规范,只能用在Web程序中,而拦截器是Sprin ...

  4. Django-restframework源码分析笔记

    在 APIview 类中的属性有一条是: authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES 定义了一个类属性为a ...

  5. C#组件系列——又一款日志组件:Elmah的学习和分享

    前言:好久没动笔了,都有点生疏,12月都要接近尾声,可是这月连一篇的产出都没有,不能坏了“规矩”,今天还是来写一篇.最近个把月确实很忙,不过每天早上还是会抽空来园子里逛逛.一如既往,园子里每年这个时候 ...

  6. 触发器 评论折叠显示(jquery)

    触发器   评论折叠显示(jquery)   子页面 : @if(Model?.count>0) {      var i=1;      var n=model.count-2      va ...

  7. 【AO笔记】有关TIN数据集的常用介绍

    写论文查了很多TIN的接口和属性,特此来记录一下. 转载请注明出处:博客园@秋意正寒,B站同名. 未完待续 1. Tin数据集在ArcGIS中的描述 Tin数据集在磁盘中,被ArcGIS以文件夹形式管 ...

  8. 键盘上的"整蛊专家",如何防止短信轰炸机

    "短信轰炸机",是别人通过爬虫或者其他抓取手段在网路上收集那些公司平台短信业务接口的一个集成程序,可能只需要输入一个手机号,对方一整天都会收到各大平台的注册或提醒短信,就是手机在那 ...

  9. 每秒生成一千万个【可视有序】分布式ID的简单方案

    去年做了一个产品,会经常导入导出大量的外部数据,这些数据的ID有的是GUID类型,有的是字符串,也有的是自增.GUID类型没有顺序,结果要排序得借助其它业务字段,整体查询效率比较低:字符串ID本来是用 ...

  10. 环境设置——pyCharm环境下导入MySQLdb遇到的一系列问题

    本文转自http://blog.sina.com.cn/s/blog_135031dae0102yc8l.html 安装好pyCharm后想要import MySQL,结果发现了一系列问题,像推到了塔 ...