解释器:执行 core,而不是认识协程
本节阅读量:surface coroutine 已经被改写成普通的 let、lambda、函数调用、set!、begin 和 record。因此解释器不需要增加一套“暂停 C++ 调用栈”的机制。
|
|
解释器看到的暂停状态是一张普通对象图:dispatcher closure 捕获 state cell,state cell 保存下一步 continuation closure。
先观察 surface 与 core
|
|
ast 保留读者写下的节点:
|
|
再看真正交给解释器的 AST:
|
|
这里已经没有 Coroutine、Yield 或 Resume,取而代之的是 $coro.* 内部名字、closure、Set、Call 和 Record。完整 dump 很长,先确认 surface 节点已经消失即可。
CLI 明确守住这条边界:
|
|
ast 是唯一停在 surface AST 的观察点;run、core、ir、alloc 和 compile 都经过同一个 pass。
旧解释器规则已经足够
| core 结构 | 已有语义 | 在 coroutine 中的职责 |
|---|---|---|
lambda |
捕获自由变量的 Location | 保存 continuation |
| 函数调用 | 执行 closure body | 执行一次 step |
let |
先求值,再分配 Location | 建立 state、finish 和临时值 |
set! |
写回已有 Location | 更换下一步 |
begin |
顺序执行 | 先安装下一步,再返回结果 |
| record | 从左到右求字段并分配 | 表示 paused/done 协议 |
第八章已经让 closure 捕获 Location,而不是某次读取出的 Value。dispatcher、当前 step 和后续 continuation 共享同一个 state Location;一个 continuation 执行 (set! state next) 后,下一次 dispatcher 调用才能读到新的 closure。
走一遍一次暂停
coroutine_one_yield.lang 的核心是:
|
|
创建 g 时只做这些事:
|
|
body 尚未执行。运行:
|
|
应输出 42,说明创建 coroutine 没有修改 body 中的 touched。
第一次 (resume g):
|
|
第二次 resume 读到刚保存的 continuation。它求值 42,调用 finish,分配 (record 1 42),再建立一个自引用的 done closure。done 每次先把自己写回 state,再返回同一个完成对象。
|
|
输出为 42。
state 临时写成 0:拒绝重入
dispatcher 的 core 形状是:
|
|
它先保存当前 step,再把共享 state 临时写成 0。正常 step 会在 yield 或完成时安装新 closure;若 step 尚未返回就再次 resume 自己,内层 dispatcher 会尝试调用 0,复用已有动态检查报告错误:
|
|
|
|
这里没有新增 coroutine 状态 tag,只是让“正在运行”暂态不可调用。
完成后不重新开始
finish 先分配完成 record,再让 state 指向捕获该 record 的自恢复 closure:
|
|
dispatcher 会在调用 done 前照常把 state 暂时清成 0;done 随即把自己写回,再返回 completed。所以完成 record 只分配一次,body 也只执行一次,而且第三次、第四次乃至更多次恢复仍然有效:
|
|
两项都输出 42。前者用 record 身份相等验证结果是同一对象,后者验证 body 中的计数器只增加一次。
独立 coroutine 是独立对象图
两个 coroutine 各有 dispatcher 和 state。交错 resume 不需要调度器:调用哪一个 dispatcher,就推进哪张对象图。
|
|
结果都为 42。嵌套 coroutine 在 validation 时开启新的 yield 边界;lowering 后只是另一组 closure 和 cell。
surface 泄漏是内部错误
解释器仍显式列出全部 kind:
|
|
这些分支不是第二份 coroutine 实现。正常 CLI 永远不会到达它们;它们负责在某条入口忘记 lowering 时立即暴露 pass 边界错误。
本节最重要的结论是:解释器没有冻结控制栈。它只是在执行 record、closure 和共享位置语义;暂停来自变换后的对象结构,而不是新的求值机器。