[Roadmap] rwir:kvlang·printlib(由 dump 改名) + 新增 kvlang·printstack —— 统一走 C ABI
归属:承接 #334(v0.2 实现层定型),落进 #330 的 B 段「rwir / stdlib 优化」。
上游动机来自 byteseek(#72/#69):agent 要在同一任务内做多轮「tool → LLM」交替,
就要把当前活动栈交给 LLM 让它决定下一步;同时把「看 layout 结果」这件事正名。
1. kvlang·dump → kvlang·printlib(改名 + 收紧语义)
dump 这个名字没表达它在做什么。它做的是把 layout 结果反出来看:签名读参数定义键、
函数体读线性指令槽,不读 .src 源码副本(layout/src/code.rs 已如此实现,但名字与文档没锁住)。
- rwir:
kvlang·dump(lib) → kvlang·printlib(lib)
- C ABI:
kvlangLayoutDump → kvlangLayoutPrintlib
- CLI:
kvlang dump <file> [prefix] → kvlang printlib <file> [prefix]
- 约束(不是新行为,是写进名字与测试的保证):禁止访问
.src。验收:dump 一次 → 删掉
该函数的 .src → 再 dump,两次输出必须逐字相同(tutorial/13-stdlib/kvlang/02-printlib.kv 已锁)。
2. 新增 kvlang·printstack(vid) -> text
printlib 覆盖 /lib(静态代码),printstack 覆盖 /vthread(动态执行态):
|
kvlang·printlib |
kvlang·printstack |
| 对象 |
/lib(layout 结果) |
/vthread/<vid>(活动栈) |
| 用途 |
审查 lower 产物、调坐标 |
停点决策:把「我在哪、手里有什么」交给 LLM |
vid 空串 = 当前 vthread(rwir 从自己的 PC 前缀 /vthread/<vid>/… 取)。
- 只读:不碰
‥pc/‥status;暂停/恢复是 harness 的事。
- 两者都实现为 C ABI(
libkvlanglayout.so 导出),保持实现统一。
实测输出形态(一个 NameError 停下的两层栈):
vthread 616 status=error frames=2
error: NameError: rwfunc not found: no_such·thing
pc: /vthread/616/[2]/[1,0]
frame[0] /lib/s_probe·outer
‥callpc = /vthread/616/[1]/[1,0]
frame[1] /lib/s_probe·inner
‥callpc = /vthread/616/[2]/[1,0]
‥returnpc = /vthread/616/[1]/[3,0]
[0,-1] = int64:3
cur = rwir|rwfunc:no_such·thing
要点(实现时踩到的,写进 issue 免得下次再猜):
- 帧目录是
/vthread/<vid>/[k]/;帧内指令槽不是帧成员——帧只存自己的实参/写参
([0,±j])与 ‥lib/‥callpc/‥returnpc/‥wdst,指令经 ‥lib 软链到函数指令树、由 PC 定位,
所以「当前指令」要直接读 PC 那个键。
- 头部字段(status/pc/错误原文/函数路径)给纯值;槽位值给
kind:value(类型有意义)。
- 值截断 200 字符,避免整份文件内容刷屏。
验收
tutorial/15-vthread/05-printstack.kv:两层栈 + NameError,断言 status=error、frames=2、
两帧函数路径、实参 int64:3、当前指令 cur = rwir|rwfunc:no_such·thing。
tutorial/13-stdlib/kvlang/02-printlib.kv:删 .src 前后输出逐字一致。
- 全套 tutorial 不回归(213 PASS / 0 FAIL / 1 SKIP)。
[Roadmap] rwir:
kvlang·printlib(由 dump 改名) + 新增kvlang·printstack—— 统一走 C ABI1.
kvlang·dump→kvlang·printlib(改名 + 收紧语义)dump这个名字没表达它在做什么。它做的是把 layout 结果反出来看:签名读参数定义键、函数体读线性指令槽,不读
.src源码副本(layout/src/code.rs已如此实现,但名字与文档没锁住)。kvlang·dump(lib)→kvlang·printlib(lib)kvlangLayoutDump→kvlangLayoutPrintlibkvlang dump <file> [prefix]→kvlang printlib <file> [prefix].src。验收:dump 一次 → 删掉该函数的
.src→ 再 dump,两次输出必须逐字相同(tutorial/13-stdlib/kvlang/02-printlib.kv已锁)。2. 新增
kvlang·printstack(vid) -> textprintlib覆盖/lib(静态代码),printstack覆盖/vthread(动态执行态):kvlang·printlibkvlang·printstack/lib(layout 结果)/vthread/<vid>(活动栈)vid空串 = 当前 vthread(rwir 从自己的 PC 前缀/vthread/<vid>/…取)。‥pc/‥status;暂停/恢复是 harness 的事。libkvlanglayout.so导出),保持实现统一。实测输出形态(一个 NameError 停下的两层栈):
要点(实现时踩到的,写进 issue 免得下次再猜):
/vthread/<vid>/[k]/;帧内指令槽不是帧成员——帧只存自己的实参/写参(
[0,±j])与‥lib/‥callpc/‥returnpc/‥wdst,指令经‥lib软链到函数指令树、由 PC 定位,所以「当前指令」要直接读 PC 那个键。
kind:value(类型有意义)。验收
tutorial/15-vthread/05-printstack.kv:两层栈 + NameError,断言status=error、frames=2、两帧函数路径、实参
int64:3、当前指令cur = rwir|rwfunc:no_such·thing。tutorial/13-stdlib/kvlang/02-printlib.kv:删.src前后输出逐字一致。