练习
本节阅读量:这一页适合读完第二章后回头做。先能解释输出,再尝试改代码。
练习 1:手画 AST
画出下面程序的 AST:
|
|
参考形状:
|
|
练习 2:追踪环境
不用写代码,只写出环境变化。
程序:
|
|
参考形式:
|
|
练习 3:手写 IR
给下面程序写出 IR:
|
|
参考形式:
|
|
注意 value 里的加法会先生成临时变量。
练习 4:判断结果
判断下面程序的结果:
|
|
再判断:
|
|
练习 5:未绑定变量
运行:
|
|
观察:
|
|
解释器和编译器都会在查找变量时发现 x 没有绑定。
练习 6:看汇编里的位置
编译:
|
|
找出:
|
|
确认外层 x 和内层 x 不是同一个位置。
练习 7:让同名变量连续编号
当前 lowerer 使用一个全局的 next_local_ 为所有 let 绑定编号。对于依次绑定 x、y、x 的程序:
|
|
生成的内部名字是:
|
|
修改内部名字的生成方式,让每个源码名字分别计数,得到:
|
|
修改后运行:
|
|
确认 IR 中同名变量的编号连续,同时程序结果仍然是 5。
这个改动只影响 IR 名字是否容易阅读,不应该改变变量查找、shadowing 或栈槽分配的行为。
练习 8:分清 value 和 body 的环境
先不要运行,判断下面程序中每个 x 对应哪一层绑定:
|
|
分别写出:
|
|
然后运行下面两个命令,检查你的推导:
|
|
重点观察:内层绑定要等 value 计算完成后才加入环境。
练习 9:变量引用会生成 IR 吗
分别查看下面两个程序的 IR:
|
|
|
|
数一数每个程序生成了多少条 copy 和多少条 add,再回答:
|
|
结合 lowerer 的 ExprKind::variable 分支解释答案。
本节目录