Skip to content

Commit bf84767

Browse files
authored
feat: WASM probe support - fix type warnings and imports (#8)
* wip: upgrade deps, add schema annotations, add wasm-probe namespace - upgrade calcit-version to 0.12.25, @calcit/procs ^0.12.25 - add packageManager yarn@4.12.0, .yarnrc.yml - upgrade CI to node 24, setup-node@v6, corepack+yarn workflow - add schema type annotations to bisection-key.core functions - add bisection-key.wasm-probe namespace with probe-bisect-basic/strings/all-count - TODO.md: document global def init issue and next steps * fix: resolve WASM type warnings, add bisect-vec/c1/c64 imports to wasm-probe, update lookup-i schema * fix: use sort+compare for get-min/max-key (compatible with string keys), update package.json scripts * fix: revert @calcit/procs to ^0.12.25 (0.12.26 not yet published) * fix: remove -1 flag from CI workflow (default is now once-only run)
1 parent 5a94972 commit bf84767

9 files changed

Lines changed: 818 additions & 2991 deletions

File tree

.github/workflows/tests.yaml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@ jobs:
1212
steps:
1313
- uses: actions/checkout@v4
1414

15-
- uses: actions/setup-node@v4
15+
- uses: actions/setup-node@v6
1616
with:
17-
node-version: 20
18-
cache: 'yarn'
17+
node-version: 24
1918

20-
- uses: calcit-lang/setup-cr@0.0.8
19+
- name: Enable Corepack
20+
run: |
21+
corepack enable
22+
corepack prepare yarn@4.12.0 --activate
23+
yarn --version
2124
22-
- name: "test"
23-
run: caps --ci && cr --entry test -1
25+
- uses: calcit-lang/setup-cr@0.0.9
2426

25-
- run: >
26-
cr -1 --entry test js
27-
&& yarn
28-
&& node test.mjs
27+
- name: Install deps
28+
run: caps --ci && yarn install --immutable
29+
30+
- name: "test cr"
31+
run: cr --entry test
32+
33+
- name: "test js"
34+
run: cr --entry test js && node test.mjs

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ js-out/
66
node_modules
77

88
example/
9+
10+
.calcit-snippets/*
11+
12+
13+
.yarn/*.gz

.yarnrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

TODO.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# bisection-key WASM 支持 TODO
2+
3+
本文件记录 WASM 编译目标的当前状态与后续工作计划。
4+
5+
---
6+
7+
## 当前状态(2026-04-22)
8+
9+
### 已完成
10+
11+
- ✅ 升级 `deps.cirru` calcit-version → `0.12.25`
12+
- ✅ 升级 `package.json``@calcit/procs ^0.12.25``packageManager: yarn@4.12.0`,新增 `test:cr` / `test:js` / `test:wasm` 脚本
13+
- ✅ 添加 `.yarnrc.yml``nodeLinker: node-modules`
14+
- ✅ 升级 CI workflow:`setup-node@v6`,node 24,Corepack + yarn@4.12.0,`caps --ci && yarn install --immutable`
15+
- ✅ 为 `bisection-key.core` 核心函数添加 schema 类型标注(`:string``:number``:bool`):
16+
- `bisect (x :string y :string) :string`
17+
- `bisect-vec (result :string xs0 :string ys0 :string idx :number) :string`
18+
- `lookup-i (c :string) :number`
19+
- `peek-tiny? (x :dynamic) :bool`
20+
- `trim-right (x :string) :string`
21+
- ✅ 新增 `bisection-key.wasm-probe` 命名空间,含 3 个 probe 函数:
22+
- `probe-bisect-basic`:验证 5 个基础 bisect 结果
23+
- `probe-bisect-strings`:验证字符串边界 bisect 结果
24+
- `probe-all-count`:返回总通过数,作为 WASM 冒烟测试的入口
25+
- ✅ WASM 编译命令(无需修改 `:entries`,直接通过 `--init-fn` 指定):
26+
```bash
27+
cr-wasm compact.cirru --init-fn bisection-key.wasm-probe/probe-all-count
28+
```
29+
30+
### 待解决:`dictionary` 全局 def 在 WASM 中为空
31+
32+
**症状**`probe-dictionary` 返回 `0`(count = 0),`bisect` 调用链内部触发 WASM `unreachable` trap。
33+
34+
**根因分析**
35+
- `dictionary` 定义为 `def dictionary $ str |+-/ |0123456789 |ABCDEFGHIJKLMNOPQRSTUVWXYZ |abcdefghijklmnopqrstuvwxyz`
36+
- `str` 内联调用本身没问题(`probe-str-inline` 验证:相同参数返回 65 字符 ✅)
37+
- 但作为全局 `def` 初始化时,WASM codegen 可能不支持在**模块初始化阶段**调用 `str` 等运行时函数
38+
- WASM 线性内存的全局变量初始化(`global.set`)只允许常量表达式,调用 host runtime 函数会被忽略或截断
39+
40+
**调试线索**
41+
- `probe-str-inline` 内联 `str` 调用 → 返回 65 ✅
42+
- `probe-dictionary` 读全局 `def dictionary` → 返回 0 ❌
43+
- 说明问题是全局 `def` 的初始化时机,不是 `str` 函数本身
44+
45+
---
46+
47+
## 后续工作计划
48+
49+
### P1:修复全局 `def` 动态初始化
50+
51+
**方案**:在 `cr-wasm` 的代码生成中,对非常量的全局 `def`(即初始化值中含有函数调用)改为**延迟初始化**
52+
53+
1. 在 WASM 模块中用 `global` 节存储 `i32`(指针),初始为 `0`(null)
54+
2. 在导出的 `__init` / `__wasm_start` 函数中,按拓扑顺序依次求值并 `global.set`
55+
3. 调用任何导出函数前,JS 侧先调用 `__init()`
56+
57+
或者更简单的方案:在 `emit_wasm.rs` 的全局 def 处理逻辑中,检测到非常量初始化时,将其改为在**第一次被读取时(lazy)**求值并缓存(惰性初始化),使用一个 `i32` flag bit 标记是否已初始化。
58+
59+
### P2:补充类型标注以提升静态路径覆盖率
60+
61+
以下函数尚无 schema 标注,可按需补充:
62+
63+
- `bisection-key.util/key-after``key-before``key-append``key-prepend`
64+
- `bisection-key.util/assoc-*` 系列
65+
- `bisection-key.util/key-nth``val-nth``key-index-of`
66+
67+
### P3:添加 WASM 专用测试脚本
68+
69+
创建 `wasm-test.mjs`,结构参考 `recollect/scripts/run-wasm-api.sh`
70+
71+
```js
72+
// wasm-test.mjs
73+
import { readFileSync } from 'fs';
74+
const mod = new WebAssembly.Module(readFileSync('js-out/program.wasm'));
75+
const inst = new WebAssembly.Instance(mod, { math: {...}, io: {...} });
76+
const e = inst.exports;
77+
78+
// 调用 __init 初始化全局 def(P1 修复后启用)
79+
// e['__init']?.();
80+
81+
const score = e['probe-all-count']();
82+
const expected = 7; // probe-bisect-basic(5) + probe-bisect-strings(2)
83+
if (score !== expected) {
84+
console.error(`WASM probe-all-count: expected ${expected}, got ${score}`);
85+
process.exit(1);
86+
}
87+
console.log(`=== bisection-key WASM probe passed: ${score}/${expected} ===`);
88+
```
89+
90+
### P4:在 CI 中加入 WASM 步骤(依赖 P1 完成)
91+
92+
`.github/workflows/tests.yaml` 补充:
93+
94+
```yaml
95+
- name: "test wasm"
96+
run: cr-wasm compact.cirru --init-fn bisection-key.wasm-probe/probe-all-count && node wasm-test.mjs
97+
```
98+
99+
---
100+
101+
## 编译验证命令速查
102+
103+
```bash
104+
# 升级依赖
105+
caps && yarn install --immutable
106+
107+
# 运行 cr 解释器测试
108+
cr --entry test -1
109+
110+
# 编译 JS 并测试
111+
cr --entry test js -1 && node test.mjs
112+
113+
# 编译 WASM(需要本地 cr-wasm binary)
114+
cr-wasm compact.cirru --init-fn bisection-key.wasm-probe/probe-all-count
115+
node wasm-test.mjs # P3 完成后可用
116+
```

0 commit comments

Comments
 (0)