本章总结
本节阅读量:第一章只支持很小的语言:
|
|
但这已经走通了一门语言实现最重要的两条路:
|
|
前半条路回答:
|
|
解释器沿着 AST 递归求值。遇到整数就返回整数,遇到加法就先求左右两边,再把结果相加。
后半条路回答:
|
|
编译器先把 AST 降成 IR,让嵌套表达式变成一行一行的计算步骤。再给每个临时变量分配栈槽:用 subq 移动 %rsp,为栈帧划出空间;用 %rbp 的负偏移稳定地读写每个栈槽;返回前再一次收回整块空间。
随后,编译器把 IR 翻译成 x86-64 AT&T 汇编。mini compile 到这里结束;离开编译器以后,我们再手动用 cc 把汇编变成可执行程序。
把两条路放在一起比较:
| 解释器 | 编译器 | |
|---|---|---|
| 共同输入 | AST | AST |
| 核心动作 | 递归求出每个节点的值 | 生成以后要执行的 IR 和汇编 |
mini 的输出 |
整数结果 | .s 汇编文件 |
| 什么时候得到结果 | 解释时立即得到 | 汇编被链接并运行以后得到 |
两条路的过程不同,但必须实现同一套语言语义。对 (+ 40 2) 来说,解释器打印 42,编译后的程序也必须返回 42。
这一章里有几个分界线很重要:
|
|
后面章节会继续扩展语言,但不会推翻这条主线。第二章加入变量和 let 后,新的问题会变成:
|
|
也就是从“只计算数字和加法”,走向“处理名字和作用域”。
本节目录