直观地说,Foo语言的编译器本身似乎不能用Foo来编写。更具体地说,Foo语言的第一个编译器不能用Foo编写,但任何后续的编译器都可以为Foo编写。
但这是真的吗?我隐约记得读过一种语言,它的第一个编译器是用“自身”编写的。这可能吗?如果可能,如何实现?
直观地说,Foo语言的编译器本身似乎不能用Foo来编写。更具体地说,Foo语言的第一个编译器不能用Foo编写,但任何后续的编译器都可以为Foo编写。
但这是真的吗?我隐约记得读过一种语言,它的第一个编译器是用“自身”编写的。这可能吗?如果可能,如何实现?
当前回答
Mono项目的c#编译器已经“自托管”很长一段时间了,这意味着它是用c#本身编写的。
据我所知,编译器最初是纯C代码,但一旦实现了ECMA的“基本”特性,他们就开始用c#重写编译器。
我不知道用同一种语言编写编译器有什么好处,但我确信它至少与语言本身可以提供的特性有关(例如,C不支持面向对象编程)。
你可以在这里找到更多信息。
其他回答
也许你可以用BNF来描述BNF。
GNAT是GNU Ada编译器,需要完全构建Ada编译器。当将其移植到一个没有现成的GNAT二进制文件的平台时,这可能是一个麻烦。
我记得我听过一个软件工程广播播客,其中Dick Gabriel谈到了如何在纸上用LISP编写一个最简单的版本,然后手工将其组装成机器代码,从而引导最初的LISP解释器。从那时起,其余的LISP特性都是用LISP编写和解释的。
一般来说,你需要先让编译器工作(如果是原始的),然后你才能开始考虑让它自托管。在某些语言中,这实际上被认为是一个重要的里程碑。
从我对“mono”的印象来看,他们很可能需要给反射添加一些东西来让它工作:mono团队一直指出,有些东西根本不可能用reflection . emit;当然,微软团队可能会证明他们错了。
这有一些真正的优点:对于初学者来说,这是一个相当好的单元测试!你只需要担心一种语言(也就是说,c#专家可能不太懂c++;但是现在你可以修复c#编译器)。但我想知道,这里是否存在某种职业自豪感:他们只是希望它能够自我托管。
不完全是编译器,但我最近一直在研究一个自托管系统;代码生成器用于生成代码生成器…所以如果模式改变了,我简单地运行它本身:新版本。如果有错误,我就返回到早期版本并重试。非常方便,也很容易维护。
更新1
我刚刚看了Anders在PDC的视频,(大约一个小时后)他给出了一些更合理的理由——都是关于编译器即服务的。只是为了记录。
Mono项目的c#编译器已经“自托管”很长一段时间了,这意味着它是用c#本身编写的。
据我所知,编译器最初是纯C代码,但一旦实现了ECMA的“基本”特性,他们就开始用c#重写编译器。
我不知道用同一种语言编写编译器有什么好处,但我确信它至少与语言本身可以提供的特性有关(例如,C不支持面向对象编程)。
你可以在这里找到更多信息。