@calcit/procs 0.12.19 → 0.12.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/install-state.gz +0 -0
- package/editing-history/202507161633-wasm-data-structures.md +61 -0
- package/editing-history/20260416-1936-predicate-narrowing-expansion.md +31 -0
- package/editing-history/202604161507-wasm-data-structures-and-rfc-rename.md +27 -0
- package/editing-history/202604161520-wasm-bitwise-and-match.md +21 -0
- package/editing-history/202604161542-wasm-cross-ns-host-imports.md +38 -0
- package/editing-history/20260417-0026-wasm-rest-args.md +62 -0
- package/editing-history/202604170048-wasm-type-of.md +70 -0
- package/editing-history/202604170051-wasm-derived-predicates.md +34 -0
- package/editing-history/202604170132-monomorphize-map-filter.md +50 -0
- package/editing-history/202604170135-monomorphize-includes-reverse.md +31 -0
- package/editing-history/202604170140-fold-type-predicates.md +44 -0
- package/editing-history/202604170154-generic-dispatch-records-tuples.md +52 -0
- package/lib/calcit.procs.mjs +39 -6
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/rfc/02-04-runtime-traits-plan.md +613 -0
- package/rfc/02-14-project-modernization-roadmap.md +229 -0
- package/rfc/02-17-register-platform-api-rfc.md +115 -0
- package/rfc/02-18-language-theory-evolution-plan.md +367 -0
- package/rfc/02-23-optional-record-macro-plan.md +30 -0
- package/rfc/03-05-function-schema-dual-track-rfc.md +162 -0
- package/rfc/03-16-runtime-boundary-refactor-plan.md +546 -0
- package/rfc/03-18-query-def-tree-show-chunked-display-plan.md +301 -0
- package/rfc/04-13-call-arg-literal-rewrite-rfc.md +205 -0
- package/rfc/04-13-type-slot-mechanism-rfc.md +194 -0
- package/rfc/04-15-match-syntax-rfc.md +175 -0
- package/rfc/04-15-type-directed-optimization-catalog.md +170 -0
- package/rfc/04-15-wasm-compilation-feasibility.md +236 -0
- package/rfc/04-16-wasm-data-structures.md +192 -0
- package/rfc/README.md +40 -0
- package/ts-src/calcit.procs.mts +33 -6
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# 项目现代化路线图(Rust 导向)
|
|
2
|
+
|
|
3
|
+
## 为什么现在做
|
|
4
|
+
|
|
5
|
+
当前架构已可用,但仍存在一些在现代 Rust 项目中通常会优先清理的可维护性热点:
|
|
6
|
+
|
|
7
|
+
- `src/` 下模块边界较宽,部分职责混合了 runtime/codegen/CLI 关注点;
|
|
8
|
+
- 仍有遗留/重复文件(例如:`src/calcit/struct.rs` 与 `src/calcit/calcit_struct.rs`);
|
|
9
|
+
- 生成产物流程依赖本地命令与脚本,尚未稳定地固化为 CI/任务体系;
|
|
10
|
+
- 基准与验证流程主要靠“口口相传”的命令知识,不是项目内的一等资产。
|
|
11
|
+
|
|
12
|
+
## 阶段 1:低风险整理(高 ROI)
|
|
13
|
+
|
|
14
|
+
### 1)移除无效/重复模块
|
|
15
|
+
|
|
16
|
+
- 候选:`src/calcit/struct.rs` 看起来是遗留文件,且未被 `src/calcit.rs` 接入。
|
|
17
|
+
- 保留 `src/calcit/calcit_struct.rs` 作为唯一权威实现。
|
|
18
|
+
|
|
19
|
+
预期收益:
|
|
20
|
+
|
|
21
|
+
- 降低核心类型导航时的认知负担;
|
|
22
|
+
- 降低“改到错误文件”的风险。
|
|
23
|
+
|
|
24
|
+
### 2)统一模块命名约定
|
|
25
|
+
|
|
26
|
+
当前风格混用了 `calcit_struct.rs` 与 `list.rs`/`tuple.rs` 这类通用命名。
|
|
27
|
+
|
|
28
|
+
建议:
|
|
29
|
+
|
|
30
|
+
- 在 `src/calcit/` 选择并坚持一种命名约定:
|
|
31
|
+
- 要么全部采用 `calcit_*.rs`;
|
|
32
|
+
- 要么全部采用类型语义命名,并由统一索引模块导出。
|
|
33
|
+
|
|
34
|
+
预期收益:
|
|
35
|
+
|
|
36
|
+
- `grep` 与跳转更直接;
|
|
37
|
+
- 对新贡献者与工具链更一致友好。
|
|
38
|
+
|
|
39
|
+
### 3)把高频检查提升为脚本/任务
|
|
40
|
+
|
|
41
|
+
将关键验证收敛为显式脚本(或任务别名),并保证输出稳定:
|
|
42
|
+
|
|
43
|
+
- 格式化/静态检查(`cargo fmt`、`cargo clippy -- -D warnings`);
|
|
44
|
+
- 编译/测试(`yarn compile`、`cargo test`、`yarn check-all`);
|
|
45
|
+
- 聚焦 JS 路径的 benchmark smoke test。
|
|
46
|
+
|
|
47
|
+
预期收益:
|
|
48
|
+
|
|
49
|
+
- 减少命令漂移;
|
|
50
|
+
- 本地开发与 CI 更容易对齐。
|
|
51
|
+
|
|
52
|
+
## 阶段 2:结构化整理(中等工作量)
|
|
53
|
+
|
|
54
|
+
### 4)将 `src/codegen/emit_js.rs` 拆为内聚子模块
|
|
55
|
+
|
|
56
|
+
`emit_js.rs` 体量较大,当前承载了多类职责:
|
|
57
|
+
|
|
58
|
+
- 符号转义;
|
|
59
|
+
- 参数/recur 模板决策;
|
|
60
|
+
- import/tag 组织;
|
|
61
|
+
- 表达式渲染。
|
|
62
|
+
|
|
63
|
+
建议:
|
|
64
|
+
|
|
65
|
+
- 按职责拆为子模块,例如:
|
|
66
|
+
- `emit_js/symbols.rs`
|
|
67
|
+
- `emit_js/functions.rs`
|
|
68
|
+
- `emit_js/imports.rs`
|
|
69
|
+
- `emit_js/tags.rs`
|
|
70
|
+
|
|
71
|
+
预期收益:
|
|
72
|
+
|
|
73
|
+
- 评审可读性更好;
|
|
74
|
+
- 后续优化时回归风险更低。
|
|
75
|
+
|
|
76
|
+
### 5)收敛 runtime helper 接口面
|
|
77
|
+
|
|
78
|
+
随着 helper 持续增加(`_args_throw`、`_args_fewer_throw`、`_args_between_throw`、`init_tags`),建议在 TS runtime 内按能力分组并形成明确边界:
|
|
79
|
+
|
|
80
|
+
- `arity helpers`;
|
|
81
|
+
- `tag helpers`;
|
|
82
|
+
- `list/map helpers` 等。
|
|
83
|
+
|
|
84
|
+
预期收益:
|
|
85
|
+
|
|
86
|
+
- JS codegen 演进更平滑;
|
|
87
|
+
- API 兼容边界更清晰。
|
|
88
|
+
|
|
89
|
+
## 阶段 3:现代 Rust 项目形态(较大工作量)
|
|
90
|
+
|
|
91
|
+
### 6)评估 Cargo workspace 拆分
|
|
92
|
+
|
|
93
|
+
可考虑的内部 crate:
|
|
94
|
+
|
|
95
|
+
- `calcit-core`(数据模型 + 求值器);
|
|
96
|
+
- `calcit-codegen-js`;
|
|
97
|
+
- `calcit-cli`。
|
|
98
|
+
|
|
99
|
+
预期收益:
|
|
100
|
+
|
|
101
|
+
- 编译影响域更小;
|
|
102
|
+
- 对外/对内 API 边界更清楚;
|
|
103
|
+
- 长期模块化能力更强。
|
|
104
|
+
|
|
105
|
+
### 7)为热点路径引入 criterion 基准
|
|
106
|
+
|
|
107
|
+
将以下基准固化为可重复执行资产:
|
|
108
|
+
|
|
109
|
+
- tail recursion 模板路径;
|
|
110
|
+
- tag 初始化开销;
|
|
111
|
+
- rest 参数转换路径。
|
|
112
|
+
|
|
113
|
+
预期收益:
|
|
114
|
+
|
|
115
|
+
- 优化决策更客观;
|
|
116
|
+
- 避免凭体感调优。
|
|
117
|
+
|
|
118
|
+
## 建议执行顺序
|
|
119
|
+
|
|
120
|
+
1. 先做 dead file 清理 + 命名规范收敛。
|
|
121
|
+
2. 再做 JS codegen 文件拆分(仅重组,不改行为)。
|
|
122
|
+
3. 引入 benchmark harness。
|
|
123
|
+
4. 边界稳定后,再评估 workspace 拆分。
|
|
124
|
+
|
|
125
|
+
## 执行追踪计划(用于持续跟踪)
|
|
126
|
+
|
|
127
|
+
> 状态约定:`TODO` / `DOING` / `DONE`
|
|
128
|
+
|
|
129
|
+
### Milestone A(稳健起步,低风险)
|
|
130
|
+
|
|
131
|
+
- [x] `DONE` 把路线图转为中文并统一结构。
|
|
132
|
+
- [x] `DONE` 清理 dead/重复模块(已移除:`src/calcit/struct.rs`)。
|
|
133
|
+
- [x] `DONE` 在关键位置补测试(覆盖 JS codegen 新模板行为):
|
|
134
|
+
- `tmpl_import_procs` 是否引入 `init_tags`;
|
|
135
|
+
- `tmpl_tags_init` 是否统一走 `init_tags(...)`;
|
|
136
|
+
- `tmpl_tail_recursion` 是否包含周期 watchdog 语义。
|
|
137
|
+
- [x] `DONE` 跑针对性测试 + 全量回归(`cargo test -q snippets::tests` / `yarn check-all`)。
|
|
138
|
+
- [x] `DONE` 将高频验证命令固化为脚本(`fmt-rs`/`lint-rs`/`test-rs`/`test-snippets`/`bench-recur-smoke`/`check-smooth`)。
|
|
139
|
+
|
|
140
|
+
验收标准:
|
|
141
|
+
|
|
142
|
+
- dead file 不再保留重复定义;
|
|
143
|
+
- 新增测试能锁定关键模板行为,避免回归;
|
|
144
|
+
- 所有验证命令通过。
|
|
145
|
+
|
|
146
|
+
### Milestone B(结构化整理)
|
|
147
|
+
|
|
148
|
+
- [ ] `DOING` 拆分 `emit_js.rs`(仅移动代码,不改变行为)。
|
|
149
|
+
- 已完成子任务:抽离 `tag_access` / `is_simple_tag_name` 到 `src/codegen/emit_js/tags.rs`,并补充对应单测。
|
|
150
|
+
- 已完成子任务:抽离 `escape_var` / `escape_cirru_str` 到 `src/codegen/emit_js/symbols.rs`,并补充对应单测。
|
|
151
|
+
- 已完成子任务:抽离 `to_js_import_name` / `to_mjs_filename` 到 `src/codegen/emit_js/paths.rs`,并补充对应单测。
|
|
152
|
+
- 已完成子任务:抽离 `get_proc_prefix` / `is_cirru_string` 到 `src/codegen/emit_js/runtime.rs`,并补充对应单测。
|
|
153
|
+
- 已完成子任务:抽离 `gen_args_code` 到 `src/codegen/emit_js/args.rs`,并补充普通参数/展开参数单测。
|
|
154
|
+
- 已完成子任务:抽离 `gen_call_args_with_temps` 及其内部判定 helper 到 `src/codegen/emit_js/args.rs`。
|
|
155
|
+
- 已完成子任务:抽离 `contains_symbol` / `sort_by_deps` 到 `src/codegen/emit_js/deps.rs`,并补充依赖判定与排序稳定性单测。
|
|
156
|
+
- 已完成子任务:抽离 `write_file_if_changed` / `is_js_unavailable_procs` / `cirru_to_js` 到 `src/codegen/emit_js/helpers.rs`,并补充基础单测。
|
|
157
|
+
- 当前策略:每次只做一个低风险子模块迁移,迁移后立即执行定向测试 + `yarn check-all`。
|
|
158
|
+
- 下一批拆分清单(按顺序执行):
|
|
159
|
+
- [x] 抽离 `get_proc_prefix` / `is_cirru_string` 到 `src/codegen/emit_js/runtime.rs`。
|
|
160
|
+
- [x] 评估并抽离参数拼接相关 helper(已完成 `gen_args_code` + `gen_call_args_with_temps`)。
|
|
161
|
+
- [x] 评估并抽离 `contains_symbol` + 依赖排序工具(若仅内部使用则独立 `deps.rs`)。
|
|
162
|
+
- [x] 抽离通用 helper(`write_file_if_changed` / `is_js_unavailable_procs` / `cirru_to_js`)。
|
|
163
|
+
- [x] `DONE` 收敛 runtime helper 分组与导出边界。
|
|
164
|
+
- [x] 已完成:将 arity helper(`_args_throw` / `_args_fewer_throw` / `_args_between_throw`)抽离到 `ts-src/js-arity-helpers.mts`。
|
|
165
|
+
- [x] 已完成:将 tag helper(`init_tags`)抽离到 `ts-src/js-tag-helpers.mts`。
|
|
166
|
+
- [x] 已完成:通过 `calcit.procs.mts` 统一 re-export,保持对外 API 名称不变。
|
|
167
|
+
- [x] 已完成:补充 runtime helper 分组说明文档(最小化一段说明,记录导出边界)。
|
|
168
|
+
- 分组边界说明:
|
|
169
|
+
- `js-arity-helpers.mts` 仅承载参数个数校验错误构造(返回 `Error`,不包含业务逻辑)。
|
|
170
|
+
- `js-tag-helpers.mts` 仅承载 tag 初始化与缓存(`init_tags` + 内部 `_tag_cache`)。
|
|
171
|
+
- `calcit.procs.mts` 作为聚合入口,负责稳定导出名,不承载上述 helper 的实现细节。
|
|
172
|
+
|
|
173
|
+
验收标准:
|
|
174
|
+
|
|
175
|
+
- 模块文件体量下降、职责更聚焦;
|
|
176
|
+
- 无行为变化,测试与 `check-all` 全通过。
|
|
177
|
+
|
|
178
|
+
### Milestone C(工程化现代化)
|
|
179
|
+
|
|
180
|
+
- [ ] `TODO` 引入 benchmark harness(优先 tail recursion/tag/rest 路径)。
|
|
181
|
+
- [ ] `TODO` 评估并设计 workspace 拆分方案(先设计后实施)。
|
|
182
|
+
|
|
183
|
+
验收标准:
|
|
184
|
+
|
|
185
|
+
- 基准可重复执行并有基线数据;
|
|
186
|
+
- workspace 拆分有明确边界与迁移顺序。
|
|
187
|
+
|
|
188
|
+
## AI 协作导向的深层规划(在关键语义不动摇前提下)
|
|
189
|
+
|
|
190
|
+
目标约束(保持不变):
|
|
191
|
+
|
|
192
|
+
- snapshot / 不可变数据模型;
|
|
193
|
+
- trait 体系与 impl 优先级语义;
|
|
194
|
+
- 宏展开能力与 hygienic 机制;
|
|
195
|
+
- JS 编译目标与运行时兼容边界。
|
|
196
|
+
|
|
197
|
+
核心方向(为 AI “错误左移 + 用法发现”服务):
|
|
198
|
+
|
|
199
|
+
1. **把左移内建到语言管线**:
|
|
200
|
+
|
|
201
|
+
- 在 reader / macroexpand / preprocess / eval 各阶段输出结构化诊断,避免问题漏到下游才暴露。
|
|
202
|
+
|
|
203
|
+
2. **把诊断做成机器可消费格式**:
|
|
204
|
+
|
|
205
|
+
- 每条错误/告警包含固定字段:阶段、错误码、主消息、期望、实际、定位信息、建议修复动作。
|
|
206
|
+
|
|
207
|
+
3. **把“正确用法”绑定到报错上下文**:
|
|
208
|
+
|
|
209
|
+
- 对常见误用(let 绑定、method 调用、trait 实现、tag-match、可调用对象)附上最小可运行示例或提示入口。
|
|
210
|
+
|
|
211
|
+
近期执行(已调整):
|
|
212
|
+
|
|
213
|
+
- [x] 移除价值较低的独立错误脚本,避免维护“脚本层契约”偏离语言内核演进目标。
|
|
214
|
+
- [x] 结构化诊断 v1 已起步:`LocatedWarning` 增加 `code/hint` 字段,并在 preprocess callable 检查接入首批错误码。
|
|
215
|
+
- [x] 已回退复杂诊断输出,当前统一使用文本诊断与 call stack/examples 指引。
|
|
216
|
+
- [x] `eval` 场景已补充 fallback 映射:参数类型错(`P_ARG_TYPE_MISMATCH`)与非可调用操作符(`P_NON_OPERATOR`)可直接结构化输出。
|
|
217
|
+
- [x] 增加宏诊断协议(code/expected/actual/action/bad/good/rule)与 CLI 解析,输出 `learning` 字段提升 LLM 学习效率。
|
|
218
|
+
- [x] 扩展高频宏入口 shape 校验(fail-fast),减少错误下沉到 `if` 等下游展开节点。
|
|
219
|
+
- [x] 修复兼容性回归并恢复主路径:`fn ()` 保持返回 `nil`,`defrecord` 保持扁平字段写法兼容(如 `defrecord Cat :name :color`)。
|
|
220
|
+
- [x] 保留并强化主路径回归:`test.cirru` + `yarn check-all`(已恢复通过)。
|
|
221
|
+
|
|
222
|
+
下一步建议(优先级顺序):
|
|
223
|
+
|
|
224
|
+
- [ ] 将当前 warning 结构扩展为统一 `CalcitDiagnostic`(含 phase/expected/actual/action),并继续覆盖 preprocess 其余高频场景。
|
|
225
|
+
- [ ] 为高频误用继续补齐错误码与修复提示模板(trait/tag-match/arity 等)。
|
|
226
|
+
- [ ] 为 eval 运行时错误补齐更多 fallback 规则(如 arity/tag-match)并加最小回归样例。
|
|
227
|
+
- [ ] 将宏诊断协议推广到更多核心宏(if/defn/assert-\*),并补 macro-level golden 诊断样例。
|
|
228
|
+
- [ ] guidebook 增加 “AI 友好排错路径” 与 “从错误到修复”最短闭环示例。
|
|
229
|
+
- [ ] 补充“宏入口校验兼容矩阵”文档,明确哪些宏允许空 body/扁平字段等历史语法,防止后续误收紧。
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# RFC: Register API / Host Capability 规范化(与当前实现对齐)
|
|
2
|
+
|
|
3
|
+
状态:Draft
|
|
4
|
+
作者:Copilot(基于当前代码审阅)
|
|
5
|
+
日期:2026-02-17
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 背景
|
|
10
|
+
|
|
11
|
+
Calcit 当前已经具备两套能力:
|
|
12
|
+
|
|
13
|
+
- 内建 proc/syntax(语言核心)
|
|
14
|
+
- 宿主注入 proc(`register_import_proc*`)
|
|
15
|
+
|
|
16
|
+
同时 FFI 入口已采用旧命名风格并在当前代码中稳定运行:
|
|
17
|
+
|
|
18
|
+
- `&call-dylib-edn`
|
|
19
|
+
- `&call-dylib-edn-fn`
|
|
20
|
+
- `&blocking-dylib-edn-fn`
|
|
21
|
+
|
|
22
|
+
ABI 版本当前为:`0.0.9`(保持不变)。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. 当前事实(对应现状)
|
|
27
|
+
|
|
28
|
+
### 2.1 注册链路
|
|
29
|
+
|
|
30
|
+
- 注册表:`IMPORTED_PROCS`
|
|
31
|
+
- 元数据表:`IMPORTED_PROC_DESCRIPTORS`
|
|
32
|
+
- 注册入口:
|
|
33
|
+
- `register_import_proc(name, f)`
|
|
34
|
+
- `register_import_proc_with_descriptor(name, f, descriptor)`
|
|
35
|
+
- 调用入口:`call_registered_proc(alias, args, call_stack)`
|
|
36
|
+
|
|
37
|
+
### 2.2 已落地校验能力
|
|
38
|
+
|
|
39
|
+
descriptor 已用于统一校验:
|
|
40
|
+
|
|
41
|
+
- 参数个数(`arity_min` / `arity_max`)
|
|
42
|
+
- 平台可用性(`platforms`)
|
|
43
|
+
- 回调最后位约束(`callback_last`)
|
|
44
|
+
- 稳定级别 warning(`stability` + once-warning)
|
|
45
|
+
|
|
46
|
+
### 2.3 FFI 注入与命名
|
|
47
|
+
|
|
48
|
+
当前注入保持旧命名风格:
|
|
49
|
+
|
|
50
|
+
- `&call-dylib-edn`
|
|
51
|
+
- `&call-dylib-edn-fn`
|
|
52
|
+
- `&blocking-dylib-edn-fn`
|
|
53
|
+
|
|
54
|
+
这与 `dylib-workflow` 当前调用方式一致。
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 3. 目标(不引入破坏性变更)
|
|
59
|
+
|
|
60
|
+
1. 保持旧 FFI 命名不变,减少用户侧迁移成本。
|
|
61
|
+
2. 在不改 ABI(`0.0.9`)前提下继续完善 descriptor 治理能力。
|
|
62
|
+
3. 统一错误语义,避免 FFI 边界 panic 直接外露。
|
|
63
|
+
4. 为后续平台能力文档化提供稳定基础。
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 4. 非目标
|
|
68
|
+
|
|
69
|
+
- 不在当前阶段切换为新命名空间形式(如 `calcit.ffi/*`)。
|
|
70
|
+
- 不在当前阶段升级 ABI 主/次版本。
|
|
71
|
+
- 不尝试统一 Rust 与 JS 的异步模型。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 5. 建议路线
|
|
76
|
+
|
|
77
|
+
### Phase A(当前可持续)
|
|
78
|
+
|
|
79
|
+
- 继续使用旧 FFI 命名。
|
|
80
|
+
- 把 descriptor 作为 host proc 的默认治理入口。
|
|
81
|
+
- 保持 ABI `0.0.9`。
|
|
82
|
+
|
|
83
|
+
### Phase B(增强稳定性)
|
|
84
|
+
|
|
85
|
+
- 统一 FFI 错误映射(符号缺失、ABI 不匹配、参数错误)。
|
|
86
|
+
- 补齐文档中的平台可用性与调用约束说明。
|
|
87
|
+
|
|
88
|
+
### Phase C(未来可选)
|
|
89
|
+
|
|
90
|
+
- 若确有收益,再讨论命名空间 API 与 ABI 演进。
|
|
91
|
+
- 必须先提供迁移文档与自动检查脚本,再做切换。
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 6. 验收标准(当前版本)
|
|
96
|
+
|
|
97
|
+
1. `dylib-workflow` 在旧命名下可直接 `cr -1` 通过。
|
|
98
|
+
2. `call_registered_proc` 校验(arity/platform/callback)持续生效。
|
|
99
|
+
3. ABI 版本保持 `0.0.9` 且调用链稳定。
|
|
100
|
+
4. 相关测试保持通过(Rust tests + workflow 冒烟)。
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 7. 决策记录(本轮)
|
|
105
|
+
|
|
106
|
+
- 采用旧命名风格优先(兼容优先)。
|
|
107
|
+
- 保留并继续使用 descriptor 机制(治理优先)。
|
|
108
|
+
- ABI 不变(风险控制优先)。
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 8. 后续维护建议
|
|
113
|
+
|
|
114
|
+
- 任何涉及 FFI 命名或 ABI 的讨论,都应先更新本 RFC。
|
|
115
|
+
- 若未来开启迁移,需在本 RFC 中追加“兼容窗口 / 回滚策略 / CI 检查项”。
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# 语言理论演进计划(law / 抽象层 / 类型驱动错误)
|
|
2
|
+
|
|
3
|
+
状态:Active
|
|
4
|
+
作者:Chen + Copilot(整理稿)
|
|
5
|
+
日期:2026-02-17
|
|
6
|
+
|
|
7
|
+
> 注(2026-02-18):`laws` 相关实现已从运行时与宏中回退,当前文档仅作为未来迭代指导,不代表已上线能力。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. 目标
|
|
12
|
+
|
|
13
|
+
基于当前 Calcit 工程现实,**逐步**推进到更“理论可解释”的语言形态,重点覆盖:
|
|
14
|
+
|
|
15
|
+
1. trait 体系补齐“法则层”(laws)与默认验证机制。
|
|
16
|
+
2. 把抽象层从 runtime 规则堆叠,收敛为“核心语义 + 推导扩展”。
|
|
17
|
+
3. 将错误报告升级为“类型驱动开发”导向(给出下一步重构建议)。
|
|
18
|
+
|
|
19
|
+
非目标:
|
|
20
|
+
|
|
21
|
+
- 不在单个版本内做破坏性重写。
|
|
22
|
+
- 不先追求完整 Haskell 化(高阶类型系统/纯粹 effect 全量引入)。
|
|
23
|
+
- 不牺牲当前可运行与可迁移性。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. 当前问题快照
|
|
28
|
+
|
|
29
|
+
### 2.1 trait 缺少 law 层
|
|
30
|
+
|
|
31
|
+
现状:`deftrait`/`defimpl`/`impl-traits` 提供了接口与实现绑定,但缺少“应满足的代数法则”声明与验证。
|
|
32
|
+
|
|
33
|
+
影响:
|
|
34
|
+
|
|
35
|
+
- 同一 trait 的不同实现行为可能不可替换。
|
|
36
|
+
- 文档约定无法自动校验,长期容易语义漂移。
|
|
37
|
+
|
|
38
|
+
### 2.2 抽象层偏实现导向
|
|
39
|
+
|
|
40
|
+
现状:不少能力以 runtime 规则累积推进,缺少“核心语义 -> 语法糖/能力层”的清晰分层。
|
|
41
|
+
|
|
42
|
+
影响:
|
|
43
|
+
|
|
44
|
+
- 新功能进入时容易引入特例。
|
|
45
|
+
- 语义一致性与可证明性不足。
|
|
46
|
+
|
|
47
|
+
### 2.3 错误报告仍偏“报错”
|
|
48
|
+
|
|
49
|
+
现状:已有 hint,但多数错误仍偏“指出失败点”,不够“指导下一步重构”。
|
|
50
|
+
|
|
51
|
+
影响:
|
|
52
|
+
|
|
53
|
+
- 学习与调试成本偏高。
|
|
54
|
+
- 类型系统价值不能完全转化为开发体验。
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 3. 总体演进策略
|
|
59
|
+
|
|
60
|
+
采用“三阶段、可回滚”的增量路线:
|
|
61
|
+
|
|
62
|
+
- **Phase A(最低风险)**:把规范写成机器可读元数据,先做到“可声明”。
|
|
63
|
+
- **Phase B(中风险)**:把声明接入检查器与测试框架,做到“可验证”。
|
|
64
|
+
- **Phase C(中高风险)**:把错误系统升级为“诊断 + 修复建议”,做到“可引导重构”。
|
|
65
|
+
|
|
66
|
+
每阶段都要求:
|
|
67
|
+
|
|
68
|
+
- 保持向后兼容(默认不破坏旧代码)。
|
|
69
|
+
- 提供 feature flag 或可配置开关。
|
|
70
|
+
- 提供对应 smoke tests。
|
|
71
|
+
|
|
72
|
+
### 3.1 保守试验约束(新增)
|
|
73
|
+
|
|
74
|
+
为避免解释器复杂度上升,所有试验默认遵循:
|
|
75
|
+
|
|
76
|
+
1. **解释器不增新分支**:不在 `evaluate_expr/call_expr` 增加语义特判。
|
|
77
|
+
2. **优先做推导层**:先在 preprocess、lint、测试框架、文档元数据落地。
|
|
78
|
+
3. **语法新增先“可降级”**:任何新声明都能被忽略或展开成现有语义。
|
|
79
|
+
4. **失败可回滚**:用 feature flag 控制,默认关闭或 warning 模式。
|
|
80
|
+
|
|
81
|
+
可接受改动层级(按优先顺序):
|
|
82
|
+
|
|
83
|
+
- 第一层:文档规范、元数据结构、CI 检查。
|
|
84
|
+
- 第二层:preprocess 诊断、`cr` 子命令扩展。
|
|
85
|
+
- 第三层:runtime 文案增强(不改求值语义)。
|
|
86
|
+
|
|
87
|
+
不建议在早期做的事:
|
|
88
|
+
|
|
89
|
+
- 新运行时值类型。
|
|
90
|
+
- 新求值规则(尤其是调用/绑定语义)。
|
|
91
|
+
- 影响现有宏展开稳定性的语法硬切换。
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. 分阶段计划
|
|
96
|
+
|
|
97
|
+
## Phase A:law 声明与语义分层清单(2~4 周)
|
|
98
|
+
|
|
99
|
+
### A1. trait law 声明(仅声明,不强制)
|
|
100
|
+
|
|
101
|
+
新增可选语法(草案级):
|
|
102
|
+
|
|
103
|
+
- 在 `deftrait` 中增加 `:laws` 区域,支持命名 law 与谓词模板。
|
|
104
|
+
- 支持 `:doc` / `:examples` 附带 law 说明。
|
|
105
|
+
|
|
106
|
+
示意:
|
|
107
|
+
|
|
108
|
+
- `Semigroup`: associativity
|
|
109
|
+
- `Monoid`: associativity + identity
|
|
110
|
+
- `Functor`: identity + composition
|
|
111
|
+
|
|
112
|
+
### A2. 核心语义分层文档化
|
|
113
|
+
|
|
114
|
+
建立一份“核心语义边界表”:
|
|
115
|
+
|
|
116
|
+
- Core(必须稳定):值模型、调用语义、绑定规则、模式匹配核心。
|
|
117
|
+
- Derived(可演进):语法糖、宏扩展、宿主能力包装。
|
|
118
|
+
- Host(平台相关):FFI、IO、环境能力。
|
|
119
|
+
|
|
120
|
+
要求每个新增功能在 PR 中标注所属层级。
|
|
121
|
+
|
|
122
|
+
### A3. 错误码分类(不改文案结构)
|
|
123
|
+
|
|
124
|
+
先统一错误类别枚举映射:
|
|
125
|
+
|
|
126
|
+
- type-mismatch
|
|
127
|
+
- arity-mismatch
|
|
128
|
+
- trait-law-violation(预留)
|
|
129
|
+
- unresolved-symbol
|
|
130
|
+
- platform-capability
|
|
131
|
+
|
|
132
|
+
> 先做分类,不强推文案重写。
|
|
133
|
+
|
|
134
|
+
### Phase A DoD
|
|
135
|
+
|
|
136
|
+
1. 至少 2 个核心 trait 支持 `:laws` 声明(可空实现)。
|
|
137
|
+
2. 发布“语义分层清单”并接入开发文档。
|
|
138
|
+
3. 错误分类映射在 runtime/preprocess 输出链路可查询。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Phase B:law 验证与抽象层约束落地(3~6 周)
|
|
143
|
+
|
|
144
|
+
### B1. law-check 框架
|
|
145
|
+
|
|
146
|
+
增加专用测试入口(例如 `check-laws`):
|
|
147
|
+
|
|
148
|
+
- 对声明了 law 的 trait,运行样例驱动验证。
|
|
149
|
+
- 支持“最小样例集 + 可扩展随机样例(可选)”。
|
|
150
|
+
|
|
151
|
+
默认策略:
|
|
152
|
+
|
|
153
|
+
- CI 先 warning 模式。
|
|
154
|
+
- 稳定后可在特定 trait 升级为 fail-on-violation。
|
|
155
|
+
|
|
156
|
+
### B2. 抽象层准入规则
|
|
157
|
+
|
|
158
|
+
新增 lint/CI 规则:
|
|
159
|
+
|
|
160
|
+
- Core 层禁止直接依赖 Host 能力。
|
|
161
|
+
- Derived 层新增语法糖时必须给出 core 等价展开。
|
|
162
|
+
- Host 能力必须显式标注平台与稳定级别。
|
|
163
|
+
|
|
164
|
+
### B3. trait 冲突的结构化报告
|
|
165
|
+
|
|
166
|
+
对于方法名冲突,不只提示“有冲突”,还输出:
|
|
167
|
+
|
|
168
|
+
- 冲突来源 trait 列表。
|
|
169
|
+
- 当前选择路径(precedence)。
|
|
170
|
+
- 推荐解法(显式 trait-call / 重命名 / 调整 impl 顺序)。
|
|
171
|
+
|
|
172
|
+
### Phase B DoD
|
|
173
|
+
|
|
174
|
+
1. 至少 1 个 trait(例如 `Monoid` 或 `Functor`)有可执行 law-check。
|
|
175
|
+
2. CI 能检查核心分层违规。
|
|
176
|
+
3. 冲突诊断包含“来源 + 选择 + 修复路径”。
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Phase C:类型驱动错误与重构建议(4~8 周)
|
|
181
|
+
|
|
182
|
+
### C1. 诊断从“错误”升级为“问题卡片”
|
|
183
|
+
|
|
184
|
+
每条关键错误输出统一包含:
|
|
185
|
+
|
|
186
|
+
- What happened
|
|
187
|
+
- Why(类型/语义原因)
|
|
188
|
+
- Next 1~2 actions(可执行)
|
|
189
|
+
- 示例链接(如 `query examples`)
|
|
190
|
+
|
|
191
|
+
### C2. 常见模式自动修复建议
|
|
192
|
+
|
|
193
|
+
先覆盖高频场景:
|
|
194
|
+
|
|
195
|
+
- 参数个数错误 -> 建议签名/调用最小改法。
|
|
196
|
+
- trait 缺失 -> 建议 `assert-traits` / `impl-traits` 路径。
|
|
197
|
+
- 平台能力错误 -> 建议替代 API 或运行目标。
|
|
198
|
+
|
|
199
|
+
### C3. 类型驱动提示入口
|
|
200
|
+
|
|
201
|
+
给开发流程增加一条轻量入口:
|
|
202
|
+
|
|
203
|
+
- `cr doctor`(草案)或现有命令扩展,汇总当前文件“下一步可修复项”。
|
|
204
|
+
|
|
205
|
+
### Phase C DoD
|
|
206
|
+
|
|
207
|
+
1. 三类高频错误具备标准化重构建议。
|
|
208
|
+
2. 错误信息可稳定指向文档/示例。
|
|
209
|
+
3. 团队内部试用反馈中,“看报错后可直接行动”的比例显著提升。
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 5. 风险与缓解
|
|
214
|
+
|
|
215
|
+
- 风险:law 语法过早固化导致后续包袱。
|
|
216
|
+
- 缓解:Phase A 仅声明,不强制;保留实验标记。
|
|
217
|
+
|
|
218
|
+
- 风险:验证框架引入 CI 波动。
|
|
219
|
+
- 缓解:先 warning,再逐步提升到 fail。
|
|
220
|
+
|
|
221
|
+
- 风险:错误文案重写工作量大。
|
|
222
|
+
- 缓解:优先高频 20% 场景,分批覆盖。
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 6. 推荐优先级(马上可做)
|
|
227
|
+
|
|
228
|
+
1. 先落地 Phase A(声明与分层)——最小改动、收益清晰。
|
|
229
|
+
2. 在 trait 体系选一个样板 trait 做 law-check 试点。
|
|
230
|
+
3. 把错误输出模板统一成“问题卡片”结构(先不做自动修复)。
|
|
231
|
+
|
|
232
|
+
### 6.1 三个“推导式优先”试点(可立即开始)
|
|
233
|
+
|
|
234
|
+
#### 试点 A:Law 只做元数据 + 测试映射
|
|
235
|
+
|
|
236
|
+
- 在 trait 文档/定义处声明 law 名称,不改变运行时行为。
|
|
237
|
+
- 由 `check-laws`(或测试脚本)把 law 名称映射到现有测试样例。
|
|
238
|
+
- 解释器零改动;收益是“语义约束可追踪”。
|
|
239
|
+
|
|
240
|
+
#### 试点 B:抽象分层只做 CI 准入
|
|
241
|
+
|
|
242
|
+
- 给模块或 PR 增加 `core/derived/host` 标签。
|
|
243
|
+
- 用静态规则检查“core 不可依赖 host”。
|
|
244
|
+
- 不改运行时;收益是“架构边界可持续维护”。
|
|
245
|
+
|
|
246
|
+
#### 试点 C:错误卡片先由 preprocess 生成
|
|
247
|
+
|
|
248
|
+
- 保留现有错误类型,仅在 preprocess 侧补 `Why/Next`。
|
|
249
|
+
- 对高频 3 类错误做模板化建议(arity、trait 缺失、平台能力)。
|
|
250
|
+
- 不改解释器求值;收益是“开发体验立即提升”。
|
|
251
|
+
|
|
252
|
+
#### 试点评估门槛(继续/停止)
|
|
253
|
+
|
|
254
|
+
- 两周内若满足以下至少两项,则继续推进:
|
|
255
|
+
- 同类问题二次出现率下降。
|
|
256
|
+
- 平均修复轮次下降。
|
|
257
|
+
- PR review 在语义争议上的耗时下降。
|
|
258
|
+
|
|
259
|
+
- 若不满足,则回滚到“仅文档+检查”层,不进入 runtime。
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 7. 评估指标(建议)
|
|
264
|
+
|
|
265
|
+
- 语义一致性:同 trait 多实现的行为偏差问题数量。
|
|
266
|
+
- 可维护性:新增功能触发的特例分支数。
|
|
267
|
+
- 开发体验:错误到修复的平均迭代次数。
|
|
268
|
+
- 迁移成本:现有项目升级失败率与修复时长。
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 8. 结论
|
|
273
|
+
|
|
274
|
+
这条路线的核心不是“追求学术完整度”,而是把学术语言里最有价值的三个能力逐步工程化:
|
|
275
|
+
|
|
276
|
+
- **可声明的语义约束(laws)**
|
|
277
|
+
- **可解释的抽象分层(core/derived/host)**
|
|
278
|
+
- **可执行的错误引导(type-driven diagnostics)**
|
|
279
|
+
|
|
280
|
+
在不破坏现有生态的前提下,这能持续提升 Calcit 的理论一致性与工程可用性。
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 9. 直接执行清单(不拆 issue)
|
|
285
|
+
|
|
286
|
+
以下清单按“尽量不增加解释器复杂度”设计,优先修改文档、preprocess、测试和 CLI 提示层。
|
|
287
|
+
|
|
288
|
+
### 9.1 第 1 步:先把 law 变成可追踪元数据(仅声明)
|
|
289
|
+
|
|
290
|
+
目标:不改求值语义,只让 trait 能表达 law 信息,并可在文档/工具中读取。
|
|
291
|
+
|
|
292
|
+
建议改动:
|
|
293
|
+
|
|
294
|
+
- 在 trait 相关文档中增加 law 字段约定(先文档约束,再代码约束)。
|
|
295
|
+
- 在 `deftrait` 相关 preprocess 路径中允许读取 `:laws`(可选,不填不影响)。
|
|
296
|
+
- law 内容先支持简单命名:`associativity`、`identity`、`composition`。
|
|
297
|
+
|
|
298
|
+
验收标准:
|
|
299
|
+
|
|
300
|
+
- 不带 `:laws` 的旧代码保持行为一致。
|
|
301
|
+
- 带 `:laws` 的定义在 preprocess 阶段可被识别并保留元信息。
|
|
302
|
+
|
|
303
|
+
当前状态:
|
|
304
|
+
|
|
305
|
+
- 暂缓执行,代码侧未启用该能力。
|
|
306
|
+
- 继续保留为后续设计入口,待语义收益明确后再推进。
|
|
307
|
+
|
|
308
|
+
### 9.2 第 2 步:增加一个最小 law-check 入口(warning 模式)
|
|
309
|
+
|
|
310
|
+
目标:用现有测试体系验证 law,不引入新运行时规则。
|
|
311
|
+
|
|
312
|
+
建议改动:
|
|
313
|
+
|
|
314
|
+
- 增加一个命令入口(可在 `cr` 子命令或测试脚本中实现)用于执行 law-check。
|
|
315
|
+
- 先对 1 个 trait 做样板(建议 `Monoid` 或 `Semigroup`)。
|
|
316
|
+
- 输出为 warning,不阻断主流程。
|
|
317
|
+
|
|
318
|
+
验收标准:
|
|
319
|
+
|
|
320
|
+
- 能输出“哪个 law 失败 + 最小反例(若可得)”。
|
|
321
|
+
- 对没有 law 声明的 trait 不做额外检查。
|
|
322
|
+
|
|
323
|
+
### 9.3 第 3 步:错误卡片化(先做 3 类高频)
|
|
324
|
+
|
|
325
|
+
目标:保留原错误类型,增强诊断信息为“可执行下一步”。
|
|
326
|
+
|
|
327
|
+
先覆盖:
|
|
328
|
+
|
|
329
|
+
- arity 错误
|
|
330
|
+
- trait 缺失/方法冲突
|
|
331
|
+
- 平台能力不匹配(如 registered proc 平台限制)
|
|
332
|
+
|
|
333
|
+
统一模板:
|
|
334
|
+
|
|
335
|
+
- What happened
|
|
336
|
+
- Why
|
|
337
|
+
- Next actions(1~2 条)
|
|
338
|
+
|
|
339
|
+
验收标准:
|
|
340
|
+
|
|
341
|
+
- 现有错误 kind 不变(兼容上层逻辑)。
|
|
342
|
+
- 至少 3 类错误能稳定输出 Next actions。
|
|
343
|
+
|
|
344
|
+
### 9.4 第 4 步:分层准入只在 CI 做
|
|
345
|
+
|
|
346
|
+
目标:限制复杂度扩散,不在 runtime 加硬编码分层判断。
|
|
347
|
+
|
|
348
|
+
建议改动:
|
|
349
|
+
|
|
350
|
+
- 增加轻量规则:Core 不直接依赖 Host。
|
|
351
|
+
- Derived 功能需提供 core 等价展开说明(文档或注释)。
|
|
352
|
+
|
|
353
|
+
验收标准:
|
|
354
|
+
|
|
355
|
+
- 新增功能 PR 必须标注层级(core/derived/host)。
|
|
356
|
+
- 规则触发时给出明确修复建议,而不是仅失败。
|
|
357
|
+
|
|
358
|
+
### 9.5 建议执行顺序与命令
|
|
359
|
+
|
|
360
|
+
推荐顺序:`9.1 -> 9.2 -> 9.3 -> 9.4`。
|
|
361
|
+
|
|
362
|
+
每步完成后建议执行:
|
|
363
|
+
|
|
364
|
+
- `cargo test`
|
|
365
|
+
- `yarn check-all`
|
|
366
|
+
|
|
367
|
+
如果某步导致复杂度明显上升(新增解释器分支、语义特判),则回滚到上一步,仅保留文档/检查器侧改动。
|