怎么研发一款编程语言? - 爱问答

(爱问答)

怎么研发一款编程语言?

对编程语言最大的误解之一,可能就是【实现一门高级语言,必须要靠更低级的语言】了。其实我们完全可以用 javaScript 实现一个 C 编译器。毕竟编译器的工作,不就是把 if else 之类的源码字符串,转换成 JMP 之类的汇编码字符串或字节码数组吗?这个输入字符串,输出字符串或数组的过程,也就是算法比较复杂,有哪门主流语言干不了吗? 可是,编译器明明生成的是机器指令,怎么可能只是倒腾字符串这么简单呢?其实像我们日常用的 gcc 就只是个壳,里面会替你依次调用预编译器 cc1、汇编器 as 和链接器 ld。经典的词法、语法、语义分析和目标代码优化等部分,都是 cc1 里做的,这时输出就是 .S 格式的汇编码字符串。至于二进制机器码的产生,靠的则是【经典编译过程结束后】汇编和链接部分的脏活。 知道了编译器的输入和输出都是字符串以后,你应该就能明白,任何图灵完备的编程语言,理论上都是能用来写编译器的。例如我们刚刚说的那种用 javaScript 编译 C 的逆向操作,就还真有人这么干(话说还有什么是 javaScript 不能写的吗): https://github.com/Captainarash/CaptCC 但是,相信题主真正想问的应该是这个问题:在没有其它高级语言的时候,那些高级语言的编译器又是怎么写出来的呢?譬如 C++ 的编译器是 C++ 写的,那第一个 C++ 编译器要怎么编译自己呢?这就是个先有鸡还是先有蛋的经典问题了。 在计算机科学里,这个问题对应于所谓的自举 (Bootstrapping) 概念。一般来说,某种新语言 X 的第一个编译器 C1,需要用另一种语言来编写。接下来你就可以用 C1 编译出一个部分用 X 来写的新编译器 C2,而 C2 又可以编译出一个支持更多 X 特性的 C3,然后 C3 编译出 X 支持更好的 C4……该过程重复 114514 次即可进化到完全自己 X 自己(误)。 更通俗的理解,是将编译器想像成一个加工零件的机床。这个机床既可以加工出普通零件,也可以加工出高级零件,最后组装出一台新的机床。第一台机床的零件都需要手工打造,造出的零件比较粗糙,但用第一台机床加工出的第二台机床,可能还有一些零件要靠手工,但机械化比例肯定比第一台机床高一些,加工效果也会更好一些。多重复几次这种【用粗糙机床制造更高精度机床】的过程后,即便制造第一台机床的手工技术失传,我们仍然可以标准化地用机床来制造机床。 历史上,最早的 C 编译器就是汇编实现的。而最早的 C++ 编译器,则是用 C with Class 这种介于 C 和 C++ 之间的语言来实现的。当时已经有了能编译 C with Class 的编译器,用这种编译器编译出来的第一个 C++ 编译器还比较简陋,只是把 C++ 转成 C,然后再用 C 编译器去编译。但有了这个起点后,人们就能用 C++ 来开发越来越强的 C++ 编译器了。所谓道生一,一生二,二生三,三生万物,大抵如此。 为了防误解,附上两个备注: 自举在技术上其实也不是必须的。理论上你也可以一直用 C 甚至汇编来实现 C++ 编译器,可是这样你干嘛还要发明 C++ 呢?但对于解释器运行时性能已经被 C++ 优化到极致的脚本语言,就没什么必要玩自举这一套。例如 javaScript 就是典型的不需要自举的语言,简称不举(误)。 只要你够牛逼,你还可以直接用自己设计的语言写出这门语言的编译器源码,然后用你的脑子把这份源码编译成该语言的第一个编译器。远古天尊 Donald Knuth 就这么干过。 思考题:虽然 javaScript 不举,但 TypeScript 和 CoffeeScript 都是自举的,为什么呢? 直到今天,我们还能看到自举的影子。例如 gcc 编译器就把自举当作了对自身的测试用例。你可以用大版本为 N-1 的旧版 gcc 构建出大版本为 N 的新版 gcc,但这个过程一共会编译三遍: 用旧版 gcc 编译出新版 gcc 用新版 gcc 编译自己 重复一次步骤 2,对比结果是否完全一致 理论依据:NewCompiler1 和 NewCompiler2 都是用相同的 NewCompiler 源码编译出的程序。它们都给定了 NewCompiler 这份源码作为相同的输入,因此不管它们自己是用什么编译器编译的(如 NewCompiler1 用的 OldCompiler 和 NewCompiler2 用的 NewCompiler1),它们所生成的输出都应该一致。所以步骤 2 和 3 所输出的 NewCompiler2 和 NewCompiler3 就也应该一致。 继续开个脑洞,假设外星人删掉了世界上所有的二进制程序和全部的代码提交历史,只留下了写在纸上的源码,那么人类的代码还怎么运行呢?表面看来,你必须从最早的 C 编译器开始写,把历史上这么多编译器陆续都实现出来自举一遍,才能最后拯救计算机文明。但是,Fabric Bellard 大神写的 TCC (Tiny CC) 就相当于一条捷径,或者说文明的火种。这个编译器的代码很少,并且不光能编译出自己,还能编译出 Linux 内核。这样,只要徒手用汇编弄出一个能编译 TCC 的更简单的 TTCC (TinyTiny CC),我们就能先用 TTCC 来编译 TCC,然后用自举后的 TCC 直接编译出 Linux 了——感觉是个程序员拯救世界的硬核科幻题材啊。

下一篇:如图,怎么解决java.nio.file.NoSuchFileException

上一篇:数据分析需要掌握哪些知识呢?

热门标签:
excel 网盘 破解 word dll
最新更新:
微软重新评估新的Outlook的使用时机 联想推出搭载联发科Helio G80芯片组的Tab M9平板 英特尔创新大赛时间确定! 微软Edge浏览器在稳定渠道中推出Workspaces功能 英伟达RTX4060TiGPU推出MaxSun动漫主题! 谷歌地图为用户提供了街景服务! GameSir 在T4 Kaleid中推出了一款出色的控制器! 微软开始在Windows 11 中测试其画图应用程序的新深色模式! LG电子推出全球首款无线OLED电视 英伟达人工智能芯片崭露头角! Steam Deck可以玩什么游戏-Steam Deck价格限时优惠 雷蛇推出CobraPro鼠标 Kindle电子阅读器可以访问谷歌商店吗 Windows10如何加入组策略 window10图片查看器怎么没有了?