也谈写写编译器

来源:互联网 发布:福建广电网络集团招聘 编辑:程序博客网 时间:2024/05/22 05:22

转自: 沈崴的日志, http://eishn.blog.163.com/blog/static/652318200961325951918/

我曾经说过初学者之所以特别热衷于写编译器、写数据库、写搜索引擎、搞 XX 智能、搞 XX 引擎、写操作系统 (读 linux 源码)之类的事情, 是因为他写不出编译器这些东西。玩不转就会觉得高深。人们都喜欢聊些看起来高深的东西,因为这很牛逼。扯啊扯的就变成了初学者中的高手。高手们正则表达式这些基础都还不会就已经会整编译器啥了。初学者有个死了也要算法的嗜好,最烦的就是正则, 缺乏算法感, 宁愿写一堆的 if 也不用, 从这点看我确实折服了。您真牛逼。其实对 unix 程序员来说,这些看上去很算法的东西, 其实还都挺容易的, 开源项目四处都是, 都玩滥了, 我们无聊时常写着玩, 真没什么好到处招呼的。

前段时间看到有人推荐的编译器设计教程, 教程说写编译器也不难, 你只要照着一步一步如此如此写就可以了, 讲得挺好。编译器这玩艺,unix/linux 下随便哪个项目为了方便都可能随手做一个, 这是 unix 程序员的基本功。只有在初学者社区,这种编程基础才会变成很牛逼的技术。可见社区基础之差、技术之烂。不过我今天在这里想说的是, 那个编译器教程看了还嫌复杂,到了今天编译器还这么写就略显老土了。

编译器, 本质上是个文本转换器,把文本代码转换成本地可执行的机器码。这其实是我们最早的做法, 编译成机器码看上去是件很牛逼的事情, 因为他很底层嘛。道理一样,很多初学者是言必称底层的, 因为基础太差玩不转所谓的底层, 所以觉得底层啊汇编啊什么的帅死了。其实别看现在那么浮躁,我们过去玩计算机的都得坐下来老老实实从计算机体系结构开始学, 我认识的一二十年的老程序员, 平时在项目里玩 python 玩得不亦乐乎,其实这些人搞搞硬件、汇编啥的都是毛毛雨, 所谓底层真没什么好到处招呼的。正因为一路从原始社会过来,用那些劳民伤财、底层低效的东西用烦了、弄怕了, 才真正觉出 python 的妙处。倒是新手还没被恶心到, 非得以底层为荣, 看不起高级的东西,偏偏还是一种沾沾自喜高人一等的神气。您真牛逼。

会点汇编在过去还真没什么, 早些时候还流行过汇编机器码对译, 简单记下对译表,直接用 01 编程了。我也记过, 早忘了, 有了 c 还用什么汇编和机器码啊。机器码、汇编、c 语言是逐行对应的, c代码在你眼前就是汇编、机器码, 就是寄存器, 就是 ip 指针, 有 c 以后就没必要用更底层的东西了。有 python 以后呢, 同样道理,python 能做的就没必要用 c 了。写个文本转换工具, 处理文本啥的 perl、python 这些语言最方便,关键是有正则可以用。可以想象在没有正则的黑暗年代, 黑客第一件事情不是把什么劳什子状态机理论搞出来, 而是把正则设计出来。先有光,然后一切都好办。言必称算法的小朋友肯定又要觉得实现正则是件很牛逼的事情了, 事实上真要去写了也就上百行代码, 也没像初学者传得那么邪门。

所以起先编译器我们直接用 c 写, 后来是 yacc/lex 用正则来刷源码, 发明一个新语言这档子事儿,就变得相当简单了。当然这还是原始社会, 新的工具, 比如 python 除了正则, 还拥有众多现代语法特性和强大的第三方工具。最近做了个Mako 的克隆, 包含判断、循环等完备的流程控制语法, 解析到输出也才三百多行。即使从来没接触过这类程序, 三百多行代码打印到一张 A4纸上, 看半天也明白了。这是技术发展到今天的惨痛后果, 还在那里很牛逼地言必称编译器, 基本上就是初学者了。

解析完源码一定要很酷地输出二进制可执行代码么? 当然不必了啦, 你可以输出 c 啊, 再把 c 编译成可执行代码。如果你能输出 c,觉着不爽要换成输出直接可执行的二进制码, 无非是查个表, 他们是可逐行翻译的嘛。所以无所谓了。在传世的 pypy 项目中, 即是把python 转换成 c、llvm、javas

cript、flex , 比神吹 java 还要跨平台。同样道理, 你甚至不用输出c, 输出 rpython 就可以了嘛。比如说 Mako 这个编译型模板, 本来就是解析输出 python 的, 到 rpython规范也就吃碗饭抽根烟的时间, 结果你得到了什么? 一个可以编译成本地二进制的极速模板, 一个可以在 javascript 甚至 flash 里面使用的编译型模板, 并且自带编译优化。

解释器就不说了, 有许多相通的地方, 只是要写一个解释型语言未必会比编译型语言更容易。