本书会讲解将源代码编译为可执行代码所需的技巧、数据结构和算法。每章节都会对应一个编译阶段。
书中会用 MiniJava 作为示例来说明如何编译一门真正的编程语言,并且每个章节后都有练习题要求实现对应的编译阶段,完成了 Part I 所有阶段的学生将会得到一个可用的编译器。
Part II 描述了如何将 MiniJava 扩展为支持类继承和高阶函数的高级技术,附录 A 中描述了 MiniJava 语言的文法。
<aside> 💬
编译器模块之间的接口和模块内部的算法一样重要
</aside>
本书会用 Java —— 一门简单的面向对象语言来进行编程。Java 是安全的,用它编写的程序无法规避类型系统来违背系统抽象;并且它有垃圾回收(GC)机制,这极大简化了动态内存分配管理。这两个特性对于实现一个编译器十分有用。
<aside> 💬
也就是说这本书会用 Java 来编写一个能够编译 MiniJava 的编译器,鸡生蛋蛋生鸡。
</aside>
如果设计者注意基本的抽象和接口,任何大型软件系统都会更容易理解和实现。图 1.1显示了典型编译器的各个阶段。每个阶段都由一个或多个软件模块来实现。
理解 abstractions:指的是用于简化和模型化复杂问题的概念
FIGURE 1. 1 编译器的各阶段和它们之间的接口
<aside> 💬
将编译器分成多部分允许组件能够更好地重用(reuse)。
</aside>
例如,要更改编译器支持的目标机器语言,只需要替换 Frame Layout(帧布局)和 Instruction Selection(指令选择)这两个阶段。要更改源语言,只需更改 Translate 之前的模块。编译器可以在Abstract Syntax 接口上连接到一个面向语言的语法编辑器。
本书中直接给出了一个项目的框架,其中的抽象和接口都经过仔细考虑,并且尽可能优雅和通用。
Part I 的各章节和编译器阶段的对应关系可以在表 1.2中查阅。这是很多编译器正在使用的框架,本书将这个框架设计得尽可能简单,并且能够在此基础上不做破坏地引入更多优化和特性。
TABLE 1.2. 编译器各阶段说明