练习
本节阅读量:这一页适合读完第三章后完成。先手算和手写,再用 mini 检查。
练习 1:画出条件 AST
画出:
|
|
参考形状:
|
|
再运行 ./mini ast <file> 对照。
练习 2:追踪 condition 和最终结果
先不要运行。对下面每个程序,分别写出:
|
|
|
|
注意区分两件事:谓词表达式产生的是 0 或 1,但整个 if 的结果来自被选中的分支,不一定也是 0 或 1。
练习 3:追踪 environment 和分支
程序:
|
|
写出:
|
|
确认内层 x 不会修改外层绑定。
练习 4:手写 IR
给下面程序写 IR:
|
|
必须包含:
|
|
然后运行 ./mini ir <file> 对照名字和顺序。
练习 5:找出基本块
查看 examples/if.lang 的 IR,把每条操作分别归入:
|
|
再画出块之间的箭头。入口块有两条出边,then0 和 else0 最后都到达 end0。
练习 6:同一个结果栈槽
编译:
|
|
在 IR 中找出两个分支共同写入的结果名,再在汇编里找出它对应的栈槽。
解释为什么栈槽分配器第二次看到同名 dst 时不能再分配一个新位置。
练习 7:嵌套 if 的标签
查看下面程序的 IR:
|
|
列出所有 then、else 和 end label,确认内外两层 if 没有使用相同名字。
练习 8:解释器与编译器一致
自己写一个同时包含 let、shadowing、eq? 和 if 的程序,并让正确结果位于 0 到 255 之间。
分别验证:
|
|
解释器输出与可执行程序退出码应该相同。
练习 9:把 not 做成语法糖
给语言增加一个一元形式:
|
|
它的语义是:
|
|
也就是说,(not expr) 等价于:
|
|
这道题的重点不是给后端增加新指令,而是练习怎样把一个表面语法复用到已有语义上。你可以选择其中一种实现方式:
|
|
完成后测试:
|
|
确认解释器和编译器的结果一致。
本节目录