补全:顺着 parent 往外查

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 补全 Scope.lookup:从自己开始,一层层沿 parent 往外找,找到就交回类型,到顶还没

开始练习 →

补全:块要开新的一层

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 贯穿的源码: let rate = 12 ; let msg = "hi" ;

开始练习 →

补全:遮蔽合法,同层重复不合法

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 下面的 declare 用 lookup 查重,把「块里再 let 一个同名」也当成了重复。补全:只

开始练习 →

数加字符串为什么错

类型只有 num / str / bool:数字是 num,字符串是 str;+ - * / 两边都是 num 得 num,+ 两边都是 str 得 str;比较运算两边同类得 bool;其余是类型不匹配。let 把名字登记进当前作用域,类

开始练习 →

比较之后是什么类型

类型只有 num / str / bool:数字是 num,字符串是 str;+ - * / 两边都是 num 得 num,+ 两边都是 str 得 str;比较运算两边同类得 bool;其余是类型不匹配。let 把名字登记进当前作用域,类

开始练习 →

赋值要核什么

类型只有 num / str / bool:数字是 num,字符串是 str;+ - * / 两边都是 num 得 num,+ 两边都是 str 得 str;比较运算两边同类得 bool;其余是类型不匹配。let 把名字登记进当前作用域,类

开始练习 →

四个表达式各是什么类型

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 类型只有 num / str / bool:数字是 num,字符串是 str;+ - * / 两边都

开始练习 →

赋错了类型

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) n 登记成 num,再把字符串赋给它: KEYWORDS = ("let", &

开始练习 →

补全:二元运算的规则

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 类型只有 num / str / bool:数字是 num,字符串是 str;+ - * / 两边都

开始练习 →

补全:赋值的类型核对

(每道题开头都有同一段:上一站的 parser(多记了位置)、show(),和错误类 SemError——错误写成一行「原因@行:列」。) 补全 check_stmt 的 assign 分支:查表拿到登记类型 t(查不到报未定义),算右边类

开始练习 →