本章总结
本节阅读量:第二章在第一章的整数和加法之外,加入了两种表达式:
|
|
程序从此不只是在计算数字,也开始处理名字和作用域。
前端为此增加了 VarExpr 和 LetExpr。parser 看到 identifier 时生成变量节点,看到 let 时读出名字、value 和 body。AST 只保存结构,不在 parser 里查找或替换变量。
解释器增加了 environment:
|
|
解释 let 时,先在旧环境中计算 value,再加入新的绑定并计算 body,最后移除这个绑定。查找变量时从后往前找,因此更近的同名绑定会暂时遮住外层绑定。
编译器也有环境,但保存的内容不同:
|
|
每个 let 绑定都会得到一个新的内部名字。即使源码里有两个同名的 x,lowering 后也可以变成 x0 和 x1,不会混在一起。
为了表示一次绑定,IR 新增了 copy:
|
|
汇编生成器沿用第一章的栈槽分配和固定栈帧,只增加一个 copy 分支,把操作数保存到目标栈槽。
这一章新增的两条路径可以写成:
|
|
它们实现的是同一套语言语义:
|
|
下一章会加入判断和 if。那时新的问题不再只是“名字指向哪里”,还包括“程序应该选择哪一条分支”。
本节目录