compile
compile 是这里第一个有趣的函数 , 它足够短 , 可以逐字包含:

文章插图
该函数处理发出模块级前奏 。
首先 , 我们为 WASM VM 发出一个编译指示以保留 3 页内存((内存 3)) , 并将堆栈指针设置为从该保留区域的末尾开始(它将向下增长) 。
然后 , 我们定义两个堆栈操作助手 __dup_i32 和 __swap_i32 。如果您曾经使用过 Forth , 这些应该很熟悉:dup 复制 WASM 堆栈顶部的项目 (a -- a a) , swap 交换 WASM 堆栈顶部两个项目的位置 (a b -- b a) 。
接下来 , 我们初始化一个堆栈帧来保存全局变量 , 使用词法分析器黑客的内置类型名初始化词法分析器 , 并咀嚼全局声明 , 直到用完为止!
最后 , 我们导出 main 并转储字符串池 。
global_declaration
这个函数太长 , 无法内联整个函数 , 但签名如下所示:
它处理 typedef、全局变量和函数 。
Typedef 很酷 , 因为这是词法分析器黑客发生的地方!
我们再一次用了通用的类型名称解析工具 , 因为 typedef 继承了所有 C 奇怪的“声明反映用法”规则 , 这对我们来说很方便 。(对于困惑的新手来说则不然!)然后我们通知词法分析器我们发现了一个新的类型名称 , 以便将来该标记将被词法分析为类型名称而不是变量名称 。
最后 , 对于 typedef , 我们将类型存储在全局 typedef 注册表中 , 使用尾随分号 , 然后返回到compile 进行下一个全局声明 。重要的是 , 我们存储的类型是一个完整解析的类型 , 因为如果你这样做 typedef int* int_p; 然后稍后写入 int_p *x , x 应该得到 int** 的结果类型 - 指针级别是累加的!这意味着我们不能只存储基本 C 类型名称 , 而是需要存储整个 CType 。
如果声明不是 typedef , 我们将解析变量类型和名称 。如果我们找到一个 ; token 我们知道它是一个全局变量声明(因为我们不支持全局初始值设定项) 。在这种情况下 , 我们将全局变量添加到全局堆栈帧和 bail 中 。
然而 , 如果没有分号 , 我们肯定正在处理一个函数 。要生成函数代码 , 我们需要:
- 为该函数创建一个新的StackFrame , 命名为frame
- 然后 , 解析所有参数并将它们存储在框架中:frame.add_var(varname.content, type, is_parameter=True)
- 之后 , 使用variable_declaration(lexer , frame)解析所有变量声明 , 这会将它们添加到frame中
- 现在我们知道函数的堆栈帧需要有多大(frame.frame_size) , 所以我们可以开始发出前奏!
- 首先 , 对于堆栈帧中的所有参数(使用 is_parameter=True 添加) , 我们生成 WASM 参数声明 , 以便可以使用 WASM 调用约定来调用该函数(在 WASM 堆栈上传递参数):
对于每个参数(按相反顺序 , 因为堆栈) , 将其从 WASM 堆栈复制到我们的堆栈:
最后 , 我们可以在循环中调用statement(lexer,frame)来代码生成函数中的所有语句 , 直到我们到达右括号:
额外步骤:我们假设函数总是有返回值 , 因此我们发出(“unreachable”) , 这样 WASM 分析器就不会崩溃 。
很多内容 , 但这就是函数的全部内容 , 因此也是 global_declaration 的全部内容 , 所以让我们继续讨论 statements 。
statement
statements 中有很多代码 。然而 , 其中大部分内容相当重复 , 因此我将只解释 while 和 for , 这应该可以提供一个很好的概述 。
还记得 WASM 没有跳转 , 而是有结构化控制流吗?现在这很重要 。
首先我们来看看它是如何与 while 配合使用的 , 在那里并不会太麻烦 。WASM 中的 while 循环如下所示:
正如所看到的 , 有两种类型的块 - 块和循环(还有 if 块类型 , 我没有使用) 。每个语句都包含一定数量的语句 , 然后以 end 结束 。在块内 , 可以使用 br 进行中断 , 或者使用 br_if 有条件地基于 WASM 堆栈的顶部(还有 br_table , 我没有使用它) 。
推荐阅读
- 曝赵丽颖怀二胎现身,冯绍峰暂停工作陪母子,冯妈送500w珠宝庆贺
- 七子白面膜粉用什么调
- 玉脏了用什么清洗最好 玉怎么清洗和保养方法
- 为什么不能用高压锅炖汤 为什么不能用高压锅压卤味
- 山姆会员卡可以借用吗 山姆会员卡是一年期还是永久
- 年初一拜神用什么供品 年初一拿什么拜神
- 皮衣保养油怎么用 保养油怎么用
- 微信亲属卡绑定信用卡怎么消费 微信亲属卡信用卡怎么开通
- 西兰花榨汁用开水焯几分钟 西兰花榨汁用开水焯多少分钟
- 用淀粉可以做肠粉吗 用淀粉能做肠粉吗
