@calcit/procs 0.12.45 → 0.12.47
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/RFCs/02-17-register-platform-api-rfc.md +1 -0
- package/RFCs/06-15-effects-graph-rfc.md +499 -0
- package/RFCs/README.md +2 -1
- package/editing-history/2026-0609-1800-core-effect-tags.md +57 -0
- package/editing-history/2026-0615-1500-effects-graph-mvp.md +30 -0
- package/editing-history/202606121525-weak-types-dots-format.md +15 -0
- package/editing-history/202606131200_primitive_schema_tags.md +9 -0
- package/editing-history/202606161700-effects-graph-ste-tree.md +84 -0
- package/editing-history/202606201142-ts-declaration-d-mts.md +5 -0
- package/lib/calcit-data.d.mts +39 -0
- package/lib/calcit.procs.d.mts +306 -0
- package/lib/custom-formatter.d.mts +8 -0
- package/lib/js-arity-helpers.d.mts +3 -0
- package/lib/js-buf-list.d.mts +11 -0
- package/lib/js-cirru.d.mts +23 -0
- package/lib/js-enum.d.mts +11 -0
- package/lib/js-impl.d.mts +15 -0
- package/lib/js-list.d.mts +61 -0
- package/lib/js-map.d.mts +60 -0
- package/lib/js-primes.d.mts +15 -0
- package/lib/js-record.d.mts +36 -0
- package/lib/js-ref.d.mts +12 -0
- package/lib/js-set.d.mts +23 -0
- package/lib/js-struct.d.mts +13 -0
- package/lib/js-tag-helpers.d.mts +2 -0
- package/lib/js-trait.d.mts +9 -0
- package/lib/js-tuple.d.mts +18 -0
- package/lib/package.json +1 -1
- package/package.json +1 -1
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
# RFC: `cr analyze effects-graph` — State / Transform / Effect 分解图
|
|
2
|
+
|
|
3
|
+
状态:Draft
|
|
4
|
+
日期:2026-06-15
|
|
5
|
+
关联:`call_tree.rs`、`analyze check-types`、`03-05-function-schema-dual-track-rfc.md`、`02-18-language-theory-evolution-plan.md`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 概要
|
|
10
|
+
|
|
11
|
+
新增分析命令:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cr analyze effects-graph [--root ns/def] [options...]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
从**入口定义**(默认 `:init-fn`)出发,把程序(及其可达子函数)分解为三类信息,并输出一张可递归展开的分析图:
|
|
18
|
+
|
|
19
|
+
| 维度 | 含义 | 典型内容 |
|
|
20
|
+
|------|------|----------|
|
|
21
|
+
| **State** | 数据与可变状态 | 参数、返回值、局部绑定、atom/ref、结构体字段流、`d!` 更新槽 |
|
|
22
|
+
| **Transform** | 纯逻辑骨架(隐藏实现细节) | 签名、控制流轮廓、调用关系、可压缩的表达式摘要 |
|
|
23
|
+
| **Effect** | 除 state 端口外的副作用 | IO、控制台、异常、环境、宿主 API、渲染、异步、watch 回调 |
|
|
24
|
+
|
|
25
|
+
设计目标:**读图即可理解程序**,而不必展开完整 Cirru 源码。
|
|
26
|
+
同一抽象可作用于整个程序,也可作用于任意单个 `ns/def` 节点(递归分解)。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. 动机
|
|
31
|
+
|
|
32
|
+
### 2.1 现有 `analyze` 能力的缺口
|
|
33
|
+
|
|
34
|
+
| 已有命令 | 提供的信息 | 不足 |
|
|
35
|
+
|----------|------------|------|
|
|
36
|
+
| `call-graph` | 定义间**调用结构** | 不区分数据流与副作用;节点仍是“函数名 + doc” |
|
|
37
|
+
| `count-calls` | 调用频次 | 无语义分类 |
|
|
38
|
+
| `program-diff` | 版本间结构 diff | 不解释运行时语义 |
|
|
39
|
+
| `check-types` / `weak-types` | 类型覆盖与薄弱点 | 不组织为可导航的“程序理解图” |
|
|
40
|
+
| `query def` / `tree show` | 完整代码 | 细节过多,不适合宏观把握 |
|
|
41
|
+
|
|
42
|
+
Agent / 人类在理解 Respo 类 UI 程序时,真正关心的是:
|
|
43
|
+
|
|
44
|
+
- 哪些**状态槽**在流动(`states`、`*abort-control`、`message-box-state`)?
|
|
45
|
+
- 哪些函数在做**纯变换**(`map`、`filter`、格式化)?
|
|
46
|
+
- 哪些调用会**触达外部世界**(`render!`、`read-file`、`js/...`、`send-to-component!`)?
|
|
47
|
+
|
|
48
|
+
`effects-graph` 把这些维度显式化。
|
|
49
|
+
|
|
50
|
+
### 2.2 与“隐藏代码细节”的关系
|
|
51
|
+
|
|
52
|
+
Transform 不等于删除逻辑,而是**降采样**:
|
|
53
|
+
|
|
54
|
+
- 保留:分支结构、循环/折叠模式、关键调用边、类型签名
|
|
55
|
+
- 省略:字面量、局部临时变量名、宏展开后的噪声
|
|
56
|
+
- 可配置:`--detail full|summary|minimal`(默认 `summary`)
|
|
57
|
+
|
|
58
|
+
类比:`call-graph` 是**结构邻接图**;`effects-graph` 是**语义分解图**。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. 核心概念
|
|
63
|
+
|
|
64
|
+
### 3.1 State
|
|
65
|
+
|
|
66
|
+
**定义**:在求值过程中可被命名、传递、持久化或观测的数据。
|
|
67
|
+
|
|
68
|
+
分类(`state.kind`):
|
|
69
|
+
|
|
70
|
+
| kind | 说明 | 检测线索 |
|
|
71
|
+
|------|------|----------|
|
|
72
|
+
| `param` | 函数入参 | `defn` 参数列表 + schema `:args` |
|
|
73
|
+
| `return` | 函数返回值 | schema `:return`、尾表达式类型 |
|
|
74
|
+
| `local` | 局部绑定 | `let` / `&let` 绑定名 + 推断类型 |
|
|
75
|
+
| `atom` | 可变引用单元 | `defatom`、`atom`、`reset!`、`swap!` |
|
|
76
|
+
| `field` | 记录/map 字段流 | `assoc`、`get`、`%{}` 构造、`:key` 读写 |
|
|
77
|
+
| `import` | 跨 ns 引入的符号 | `:require` / `:refer` 解析结果 |
|
|
78
|
+
| `slot` | 框架约定状态槽 | Respo `states`、`d!` 第一参数模式 |
|
|
79
|
+
|
|
80
|
+
**State 端口(port)**:带方向的类型化槽位,形如:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"id": "app.comp.container/message-box-state:content",
|
|
85
|
+
"kind": "field",
|
|
86
|
+
"type": ":string",
|
|
87
|
+
"direction": "inout",
|
|
88
|
+
"source": "app.comp.container/comp-message-box:3.2"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`direction`:`in` | `out` | `inout` | `persist`(跨 reload 保留,如 atom)。
|
|
93
|
+
|
|
94
|
+
### 3.2 Transform
|
|
95
|
+
|
|
96
|
+
**定义**:在 state 端口之间建立映射的**可命名逻辑单元**,实现细节在输出中默认折叠。
|
|
97
|
+
|
|
98
|
+
一个 Transform 节点包含:
|
|
99
|
+
|
|
100
|
+
- `signature`:来自 `CodeEntry.:schema` 或 `hint-fn` 补全结果
|
|
101
|
+
- `control`:压缩后的控制流骨架(`if` / `cond` / `match` / `foldl` / `let` 深度)
|
|
102
|
+
- `calls`:调用的其他 Transform(指向子节点或外部 `fqn`)
|
|
103
|
+
- `summary`:一句话摘要(可选,来自 `:doc` 首行或规则生成)
|
|
104
|
+
|
|
105
|
+
示例(概念输出):
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
└── app.comp.container/comp-message-box [transform]
|
|
109
|
+
├── state.in message-box-state (:record)
|
|
110
|
+
├── state.out message-box-state (:record)
|
|
111
|
+
├── control let → if focus-mode? → textarea | compact-div
|
|
112
|
+
├── calls respo.core/textarea, respo.core/div, calcit.core/assoc
|
|
113
|
+
└── effects (none in pure branch)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**宏展开策略**:分析期展开一层;展开结果并入 Transform,不单独暴露宏内部符号(与 `call-graph` 跳过 macro 体一致)。
|
|
117
|
+
|
|
118
|
+
### 3.3 Effect
|
|
119
|
+
|
|
120
|
+
**定义**:改变外部世界、控制流、可观测性,或引入**非局部**语义的运算;**不把**已在 State 端口建模的纯数据传递算作 effect。
|
|
121
|
+
|
|
122
|
+
分类(`effect.kind`,第一版内置表):
|
|
123
|
+
|
|
124
|
+
| kind | 示例 | 类型标记 |
|
|
125
|
+
|------|------|----------|
|
|
126
|
+
| `console` | `println`, `eprintln`(若可静态识别) | `:effect/console` |
|
|
127
|
+
| `io/read` | `read-file` | builtin schema |
|
|
128
|
+
| `io/write` | `write-file` | builtin schema |
|
|
129
|
+
| `env` | `get-env` | builtin schema |
|
|
130
|
+
| `control/raise` | `raise` | builtin schema |
|
|
131
|
+
| `control/quit` | `quit!` | builtin schema |
|
|
132
|
+
| `async` | `hint-fn $ {} (:async true)` 作用域 | `:effect/async` |
|
|
133
|
+
| `state/watch` | `add-watch` / `remove-watch` | `:effect/watch` |
|
|
134
|
+
| `render` | `render!`, `clear-cache!` | 模块规则 + schema |
|
|
135
|
+
| `interop/js` | `js/...`, `&js-object`, `js-await` | `:effect/js` |
|
|
136
|
+
| `interop/host` | `register_import_proc` 注入 proc | descriptor 元数据 |
|
|
137
|
+
| `platform` | `register-calcit-platform-api` 能力 | platform API RFC |
|
|
138
|
+
| `unknown` | 无法分类的 `:dynamic` 调用 | 需补全 schema |
|
|
139
|
+
|
|
140
|
+
Effect 边:从 Transform 节点指向 effect 节点;effect 节点可带 `target`(文件路径、DOM、atom 名等)若可静态推导。
|
|
141
|
+
|
|
142
|
+
**与 State 的边界规则**:
|
|
143
|
+
|
|
144
|
+
- `assoc state :content x` → **state** 更新(field inout)
|
|
145
|
+
- `reset! *counter 1` → **state**(atom persist)+ 可选标 `effect/state-mutate`(若需区分“突变事件”)
|
|
146
|
+
- `render! (comp-container ...)` → **effect**(UI 输出),其参数中的 state 仍归 State 分析
|
|
147
|
+
|
|
148
|
+
第一版建议:**突变写入归 State,对外可观测归 Effect**,避免双重计数。
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 4. 与 Koka effect typing 的关系(借鉴而非照搬)
|
|
153
|
+
|
|
154
|
+
Koka 核心思想:函数类型携带 effect row,例如 `f : int -> console string`。
|
|
155
|
+
|
|
156
|
+
```koka
|
|
157
|
+
fun greet(name: string) : console ()
|
|
158
|
+
println("hello " ++ name)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Calcit **不**在第一阶段引入完整 effect handler 语义(见 `02-18-language-theory-evolution-plan.md` 非目标),但借鉴:
|
|
162
|
+
|
|
163
|
+
| Koka 概念 | Calcit 对应(分阶段) |
|
|
164
|
+
|-----------|----------------------|
|
|
165
|
+
| effect row `<console, exn>` | `CodeEntry.:schema` 新增可选 `:effects` 列表 |
|
|
166
|
+
| pure function `()` | `:effects $ []` 或省略 |
|
|
167
|
+
| handled effect | 仅分析期标注,不要求 handler 语法 |
|
|
168
|
+
| `perform` / `ctl` | 无;用 builtin / 调用模式识别 |
|
|
169
|
+
| row polymorphism | 第二版:`:effects $ [] 'e` 泛型行变量(可选) |
|
|
170
|
+
|
|
171
|
+
### 4.1 建议的 schema 扩展(Phase B)
|
|
172
|
+
|
|
173
|
+
在现有 `:: :fn` payload 中增加:
|
|
174
|
+
|
|
175
|
+
```cirru
|
|
176
|
+
:schema $ :: :fn
|
|
177
|
+
{}
|
|
178
|
+
:args $ [] :dynamic
|
|
179
|
+
:return :dynamic
|
|
180
|
+
:effects $ [] :console :render
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
或独立 effect 声明(`defeffect` 已在 snapshot 词法表预留,尚未实现):
|
|
184
|
+
|
|
185
|
+
```cirru
|
|
186
|
+
defeffect Render
|
|
187
|
+
.mount :fn
|
|
188
|
+
.patch :fn
|
|
189
|
+
|
|
190
|
+
defn render-once (ui) $
|
|
191
|
+
hint-fn $ {} (:effects $ [] :render)
|
|
192
|
+
render! ui
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
第一版 **不强制** 用户手写;`effects-graph --infer-missing` 可生成建议补丁。
|
|
196
|
+
|
|
197
|
+
### 4.2 内置 proc 的 effect schema
|
|
198
|
+
|
|
199
|
+
**首选数据源**:`calcit-core.cirru` 各 builtin 定义的 `:tags` 字段。分析器按 tag 映射到 effect kind,无需维护独立硬编码表。
|
|
200
|
+
|
|
201
|
+
#### Tag 约定(calcit.core)
|
|
202
|
+
|
|
203
|
+
| Tag | 含义 | 典型定义 |
|
|
204
|
+
|-----|------|----------|
|
|
205
|
+
| `:state` | 可变引用 / 本地可变容器 | `defatom`, `atom`, `reset!`, `swap!`, `deref`, `ref?`, `add-watch`, `remove-watch`, `&atom:deref`, `&buf-list:*` |
|
|
206
|
+
| `:io` | 宿主 / 运行时交互 | `read-file`, `write-file`, `get-env`, `cpu-time`, `&get-os`, `&get-calcit-*`;`println`/`eprintln`/`echo` 为宿主注入 |
|
|
207
|
+
| `:file` | 文件读写(`:io` 子类) | `read-file`, `write-file` |
|
|
208
|
+
| `:env` | 环境变量(`:io` 子类) | `get-env` |
|
|
209
|
+
| `:log` | 控制台输出(`:io` 子类) | `println`, `eprintln`, `echo`(宿主注入,见 Phase C) |
|
|
210
|
+
| `:control` | 控制流中断 | `raise`, `quit!`, `try`;测试宏 `assert`/`assert=`/`assert-detect`(失败时 `raise` + `eprintln`) |
|
|
211
|
+
| `:interop` | 宿主 FFI / dylib / 动态求值 | `&call-dylib-edn*`, `eval`, `js-object` |
|
|
212
|
+
| `:meta` | 程序自省 / 编译期元数据 | `&get-def-doc`, `&get-def-schema`, `macroexpand*`, `assert-type`, `deftype-slot`, `with-type-slot`, `&data-to-code`, `&extract-code-into-edn` |
|
|
213
|
+
| `:async` | 异步标记(经 `hint-fn`) | `hint-fn` |
|
|
214
|
+
| `:watch` | atom 监听回调 | `add-watch`, `remove-watch`(与 `:state` 叠加) |
|
|
215
|
+
| `:effect` | 显式副作用组合子 | `&doseq` |
|
|
216
|
+
|
|
217
|
+
映射示例(tag → effects-graph kind):
|
|
218
|
+
|
|
219
|
+
- `read-file` (`:io` `:file`) → `[:io/read]`
|
|
220
|
+
- `write-file` (`:io` `:file`) → `[:io/write]`
|
|
221
|
+
- `raise` (`:control`) → `[:control/raise]`
|
|
222
|
+
- `get-env` (`:io` `:env`) → `[:env]`
|
|
223
|
+
- `reset!` / `swap!` (`:state`) → `[:state/write]`
|
|
224
|
+
- `add-watch` (`:state` `:watch`) → `[:state/watch]`
|
|
225
|
+
- `eval` (`:interop`) → `[:interop/eval]`
|
|
226
|
+
- `hint-fn` (`:async`) → 分析子函数 `:effects` 行
|
|
227
|
+
- `&doseq` (`:effect`) → body 内 effect 边展开
|
|
228
|
+
- `println` (`:log` `:io`) → `[:console]`
|
|
229
|
+
|
|
230
|
+
宿主注入 proc 通过 `RegisteredProcDescriptor.tags`(`HashSet<EdnTag>`,与 core `:tags` 同名)声明;可用 `cr query host-procs [--tag :log]` 查看。
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 5. 命令设计
|
|
235
|
+
|
|
236
|
+
### 5.1 语法
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
cr analyze effects-graph [options]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
与 `call-graph` 对齐的选项:
|
|
243
|
+
|
|
244
|
+
| 选项 | 说明 | 默认 |
|
|
245
|
+
|------|------|------|
|
|
246
|
+
| `--root ns/def` | 入口定义 | `:init-fn` |
|
|
247
|
+
| `--format tree\|json\|mermaid` | 输出格式 | `tree` |
|
|
248
|
+
| `--max-depth N` | 子图展开深度 | 无限制 |
|
|
249
|
+
| `--include-core` | 包含 `calcit.core` 节点 | false |
|
|
250
|
+
| `--ns-prefix PREFIX` | 只保留匹配 ns 子树 | 无 |
|
|
251
|
+
| `--detail summary\|full\|minimal` | Transform 压缩级别 | `summary` |
|
|
252
|
+
| `--infer-missing` | 输出类型/effect 补全建议 | false |
|
|
253
|
+
| `--show-transform-body` | 在 summary 模式下仍输出骨架 AST | false |
|
|
254
|
+
|
|
255
|
+
### 5.2 输出格式
|
|
256
|
+
|
|
257
|
+
## 输出格式(tree)
|
|
258
|
+
|
|
259
|
+
默认 `--max-depth 1`:先展示入口 **Program Overview**(独立 STE 三棵树),子图以索引列出并标注 `[collapsed]`,按需 `--root ns/def` 或增大 `--max-depth` 展开。
|
|
260
|
+
|
|
261
|
+
`--max-depth 0`(无限制)时额外输出 **§2 Subgraph Trees**,每个子函数各一棵独立 STE 树。
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
# Effects Graph
|
|
265
|
+
Entry: app.main/main!
|
|
266
|
+
|
|
267
|
+
## app.main/main! [program]
|
|
268
|
+
├── state
|
|
269
|
+
│ ├── import util.core/log-title
|
|
270
|
+
│ └── ...
|
|
271
|
+
├── transform (summary)
|
|
272
|
+
│ └── sequential: 24 test modules, 3 branches
|
|
273
|
+
└── effects
|
|
274
|
+
└── console println (×N)
|
|
275
|
+
|
|
276
|
+
└── app.comp.container/comp-container [transform]
|
|
277
|
+
├── state.in states (:map)
|
|
278
|
+
├── state.out states (:map)
|
|
279
|
+
├── transform comp-message-box → comp-sessions-modal
|
|
280
|
+
└── effects
|
|
281
|
+
├── render respo.core/render!
|
|
282
|
+
└── interop respo.controller.client/send-to-component!
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### json
|
|
286
|
+
|
|
287
|
+
机器消费;节点类型:`program | transform | state_port | effect`。
|
|
288
|
+
|
|
289
|
+
#### mermaid(默认,birdview)
|
|
290
|
+
|
|
291
|
+
专注快速理解程序:**State** 数据结构与类型、**Transform** 关键函数连接、**Effects** 副作用种类。
|
|
292
|
+
|
|
293
|
+
```mermaid
|
|
294
|
+
flowchart LR
|
|
295
|
+
subgraph stateLane["State"]
|
|
296
|
+
s0["states<br/>:map"]
|
|
297
|
+
end
|
|
298
|
+
subgraph transformLane["Transform"]
|
|
299
|
+
t0["main!"]
|
|
300
|
+
t1["comp-container"]
|
|
301
|
+
end
|
|
302
|
+
subgraph effectLane["Effects"]
|
|
303
|
+
e0[[render]]
|
|
304
|
+
end
|
|
305
|
+
t0 -->|call| t1
|
|
306
|
+
t1 -.->|state| s0
|
|
307
|
+
t1 ==>|effect| e0
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
- 蓝 = State(`name<br/>:type`)
|
|
311
|
+
- 黄 = Transform(关键 `ns/def` 简名)
|
|
312
|
+
- 红 = Effect(按 kind 聚合,隐藏具体 proc 细节)
|
|
313
|
+
- `-->` 函数调用 · `-.->` 状态关联 · `==>` 触发副作用
|
|
314
|
+
|
|
315
|
+
### 5.3 与 `call-graph` 的组合
|
|
316
|
+
|
|
317
|
+
推荐工作流:
|
|
318
|
+
|
|
319
|
+
1. `cr analyze call-graph` — 看清**可达定义集合**
|
|
320
|
+
2. `cr analyze effects-graph` — 在同一入口上读**语义分解**
|
|
321
|
+
3. `cr analyze check-types --infer-missing` + `effects-graph --infer-missing` — 补齐 schema
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 6. 分析管线(实现架构)
|
|
326
|
+
|
|
327
|
+
### 6.1 模块划分
|
|
328
|
+
|
|
329
|
+
新增 `src/effects_graph.rs`(库模块),CLI 入口挂到 `cr analyze`(`cli_args.rs` / `cr.rs`),与 `call_tree` 并列。
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
effects_graph/
|
|
333
|
+
mod.rs # 公共类型、入口 analyze_effects_graph()
|
|
334
|
+
extract.rs # 从 Calcit/Cirru 提取 STE
|
|
335
|
+
classify.rs # proc/call → effect kind
|
|
336
|
+
state.rs # 参数、let、atom、assoc 数据流
|
|
337
|
+
transform.rs # 控制流骨架 + summary 生成
|
|
338
|
+
infer.rs # 缺 schema 时的补全建议
|
|
339
|
+
format.rs # tree / json / mermaid
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**不修改求值语义**;仅在 preprocess 之后的 `PROGRAM_CODE_DATA` + `CompiledDef` 上只读分析(符合 `02-18` 保守试验约束)。
|
|
343
|
+
|
|
344
|
+
### 6.2 数据来源优先级
|
|
345
|
+
|
|
346
|
+
| 信息 | 来源 1 | 来源 2 | 来源 3 |
|
|
347
|
+
|------|--------|--------|--------|
|
|
348
|
+
| 参数/返回类型 | `CodeEntry.:schema` | `hint-fn` | 推断 `weak-types` |
|
|
349
|
+
| 文档摘要 | `&get-def-doc` / `entry.doc` | — | — |
|
|
350
|
+
| 调用目标 | `call_tree` 同款 `extract_calls` | — | — |
|
|
351
|
+
| Effect 种类 | builtin proc 表 | `:effects` schema | 启发式(`js/` 前缀) |
|
|
352
|
+
| State 槽 | schema + `assoc`/`get` 模式 | atom 表 | — |
|
|
353
|
+
|
|
354
|
+
### 6.3 Transform 压缩算法(summary 模式)
|
|
355
|
+
|
|
356
|
+
1. 对 `defn` 体做**浅层**遍历,深度上限 `D=3`(可配置)
|
|
357
|
+
2. 保留:`if/cond/match/foldl/map/filter/let` 节点类型与子节点**类型标签**
|
|
358
|
+
3. 替换:字面量 → `_`;长字符串 → `"..."` ;大块 `quote` → `⟨quoted⟩`
|
|
359
|
+
4. 生成 `summary`:优先 `doc` 首句,否则模板 `"let×N, if×M, calls K"`
|
|
360
|
+
|
|
361
|
+
`full` 模式:输出类似 `cr tree show --chunked` 的分片骨架(见 `03-18-query-def-tree-show-chunked-display-plan.md`),但不输出完整叶子。
|
|
362
|
+
|
|
363
|
+
### 6.4 类型补全(`--infer-missing`)
|
|
364
|
+
|
|
365
|
+
当某 `ns/def` 缺少 `:schema` 或 `:effects` 时:
|
|
366
|
+
|
|
367
|
+
1. 用现有 `analyze_code_entry` / type inference 收集 `:args`/`:return` 候选
|
|
368
|
+
2. 用 effect 分类器扫描函数体,汇总 effect 集合
|
|
369
|
+
3. 输出 unified diff 建议(仅 stdout 或 `--write-suggestions file` 未来扩展)
|
|
370
|
+
|
|
371
|
+
示例建议块:
|
|
372
|
+
|
|
373
|
+
```text
|
|
374
|
+
## Suggested schema patch: app.comp.container/comp-message-box
|
|
375
|
+
:schema $ :: :fn
|
|
376
|
+
{}
|
|
377
|
+
:args $ [] :dynamic
|
|
378
|
+
:return :dynamic
|
|
379
|
+
:effects $ [] :render :console
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
与 `cr edit` 集成留作 Phase C。
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 7. 分阶段实施计划
|
|
387
|
+
|
|
388
|
+
### Phase A — 只读分析 MVP(4~6 周)
|
|
389
|
+
|
|
390
|
+
**交付**:
|
|
391
|
+
|
|
392
|
+
- [x] `cr analyze effects-graph` tree + json 输出
|
|
393
|
+
- [x] 入口可达分析(复用 `CallTreeAnalyzer` 可达集)
|
|
394
|
+
- [x] State:`param` / `return` / `local` / `atom` 基础识别
|
|
395
|
+
- [x] Effect:builtin proc 表(core 全覆盖)
|
|
396
|
+
- [x] Transform:`summary` 模式 + `calls` 边
|
|
397
|
+
- [x] 测试:`calcit/test-effects-graph.cirru`(纯 calcit 小程序,不依赖 respo)
|
|
398
|
+
|
|
399
|
+
**非目标**:`:effects` schema、`defeffect`、mermaid、自动写回 snapshot。
|
|
400
|
+
|
|
401
|
+
### Phase B — 类型驱动 + 框架规则(4 周)
|
|
402
|
+
|
|
403
|
+
**交付**:
|
|
404
|
+
|
|
405
|
+
- [ ] `CodeEntry.:schema` 支持 `:effects` 列表(解析 + `check-types` 统计)
|
|
406
|
+
- [ ] Respo 规则包:`render!`、`d!`、`send-to-component!` 静态识别
|
|
407
|
+
- [ ] `--infer-missing` 建议输出
|
|
408
|
+
- [ ] `mermaid` 格式
|
|
409
|
+
- [ ] 文档:`docs/features/effects-graph.md`
|
|
410
|
+
|
|
411
|
+
### Phase C — 生态与编辑器集成(后续)
|
|
412
|
+
|
|
413
|
+
- [x] `RegisteredProcDescriptor.tags`(与 core `:tags` 对齐)
|
|
414
|
+
- [ ] `defeffect` 语法落地(可选)
|
|
415
|
+
- [ ] `cr analyze effects-graph-diff <git-ref>`(对齐 `program-diff`)
|
|
416
|
+
- [ ] Agent 指南:`cr docs agents` 增加 effects-graph 工作流
|
|
417
|
+
- [ ] 与 `query def` 联动:`cr query def ns/def --view effects`
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 8. 示例:Respo UI 程序片段
|
|
422
|
+
|
|
423
|
+
入口:`app.comp.container/comp-container`(msg-buffer 类项目)。
|
|
424
|
+
|
|
425
|
+
预期分解(示意):
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
app.comp.container/comp-container
|
|
429
|
+
├── state
|
|
430
|
+
│ ├── param states (:map) # Respo 组件状态
|
|
431
|
+
│ ├── param cursor (:fn) # d! 回调
|
|
432
|
+
│ ├── local message-box-state
|
|
433
|
+
│ └── atom *abort-control (persist)
|
|
434
|
+
├── transform
|
|
435
|
+
│ ├── comp-message-box(states, cursor)
|
|
436
|
+
│ ├── comp-sessions-modal(...)
|
|
437
|
+
│ └── cond done? / streaming? / ...
|
|
438
|
+
└── effects
|
|
439
|
+
├── render respo.core/render!
|
|
440
|
+
├── interop feather.core/comp-i
|
|
441
|
+
├── console println (tests only)
|
|
442
|
+
└── watch (if add-watch present)
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
读者**无需打开** 1500 行 `calcit.cirru` 即可理解:状态在 `states` / `message-box-state`,UI 通过 `render!` 输出,流式中止走 `*abort-control`。
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## 9. 测试策略
|
|
450
|
+
|
|
451
|
+
| 层级 | 内容 |
|
|
452
|
+
|------|------|
|
|
453
|
+
| 单元测试 | `classify_effect`, `extract_state_ports`, `compress_transform` |
|
|
454
|
+
| 集成测试 | 对 `calcit/test-effects-graph.cirru` 跑 `cr analyze effects-graph --format json`,快照比对 |
|
|
455
|
+
| 回归 | 不改变现有 `call-graph` / `check-types` 行为 |
|
|
456
|
+
| 可选 | msg-buffer / respo 手工验收(不纳入 CI 硬依赖) |
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## 10. 非目标(第一版)
|
|
461
|
+
|
|
462
|
+
- 不实现 Koka 式 `with/handler` 运行时语义
|
|
463
|
+
- 不改变 JS / WASM codegen
|
|
464
|
+
- 不做跨进程 / 网络 effect 的自动发现(除非显式 builtin)
|
|
465
|
+
- 不保证 whole-program 数据流**完备**(Halting 与动态调用不可判定)
|
|
466
|
+
- 不把 `effects-graph` 当作安全沙箱策略
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## 11. 开放问题
|
|
471
|
+
|
|
472
|
+
1. **Transform 压缩深度默认值**:`D=3` 是否足够表达 Respo 组件?需用 msg-buffer 实测。
|
|
473
|
+
2. **`d!` 语义**:算 state 突变还是 effect?建议 state,但是否要单独 `effect/state-notify`?
|
|
474
|
+
3. **宏生成代码**:`quasiquote` 残留是否进入 Transform?建议分析**展开后** IR。
|
|
475
|
+
4. **递归节点展开**:同一 `fqn` 多次出现是 inline 子图还是 `seen` 引用(对齐 call-graph)?
|
|
476
|
+
5. **`:effects` 与 `:return` 交叉**:`:: :fn {:return :unit}` 且含 `:console` 是否强制标注?建议 warning。
|
|
477
|
+
6. **`defeffect` 与 `deftrait` 关系**:effect 是否复用 trait 机制?第一版独立,避免混淆。
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## 12. 与现有 RFC 的衔接
|
|
482
|
+
|
|
483
|
+
| 文档 | 关系 |
|
|
484
|
+
|------|------|
|
|
485
|
+
| `03-05-function-schema-dual-track-rfc.md` | `:schema` 是 State/Transform 签名的主来源;本 RFC 扩展 `:effects` |
|
|
486
|
+
| `02-18-language-theory-evolution-plan.md` | 分析层优先、不求值语义变更 |
|
|
487
|
+
| `02-17-register-platform-api-rfc.md` | 宿主 proc effect 描述符 |
|
|
488
|
+
| `03-16-runtime-boundary-refactor-plan.md` | 长期 state slot 与 ref 显式化可强化 State 分析 |
|
|
489
|
+
| `05-12-program-diff-rfc.md` | 未来 `effects-graph-diff` 可对比 STE 结构变化 |
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## 13. 验收标准(Phase A)
|
|
494
|
+
|
|
495
|
+
- [ ] `cargo run --bin cr -- calcit/test.cirru analyze effects-graph` 成功退出
|
|
496
|
+
- [ ] 输出包含 entry 的 state / transform / effect 三节
|
|
497
|
+
- [ ] `read-file` 调用归类为 `io/read`,不落在 transform 摘要正文中
|
|
498
|
+
- [ ] `--format json` 可被 `jq` 解析,节点含 `fqn`、`kind`
|
|
499
|
+
- [ ] 文档与本 RFC 同步进入 `RFCs/README.md`
|
package/RFCs/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RFC 整理索引
|
|
2
2
|
|
|
3
|
-
更新时间:2026-
|
|
3
|
+
更新时间:2026-06-15
|
|
4
4
|
|
|
5
5
|
## 目录原则
|
|
6
6
|
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
| `04-15-wasm-compilation-feasibility.md` | Active | WASM 编译三条路径(解释器→WASM / AOT 子集 / WASM GC)的可行性评估。 |
|
|
28
28
|
| `04-16-wasm-data-structures.md` | Active | WASM codegen 中 Tag/Record/Tuple 等数据结构的内存布局与编译策略。 |
|
|
29
29
|
| `05-31-generic-where-bounds-mfs.md` | Active | 函数 schema 泛型 `:where` 约束的最小功能规格,先作为主链路开发基线。 |
|
|
30
|
+
| `06-15-effects-graph-rfc.md` | Draft | `cr analyze effects-graph`:State/Transform/Effect 语义分解图与类型驱动 effect 标注路线。 |
|
|
30
31
|
|
|
31
32
|
## 已执行的清理
|
|
32
33
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# calcit-core / RegisteredProcDescriptor effect tags
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
|
|
5
|
+
为 `cr analyze effects-graph` 静态分析补充 effect 标记,数据源分两处、tag 名称统一:
|
|
6
|
+
|
|
7
|
+
1. **`calcit-core.cirru`** — builtin CodeEntry 的 `:tags`
|
|
8
|
+
2. **宿主注入 proc** — `RegisteredProcDescriptor.tags`(`HashSet<EdnTag>`)
|
|
9
|
+
|
|
10
|
+
RFC `06-15-effects-graph-rfc.md` §4.2 已同步完整 tag 约定表。
|
|
11
|
+
|
|
12
|
+
## calcit.core Tag 分类
|
|
13
|
+
|
|
14
|
+
| Tag | 目标 |
|
|
15
|
+
|-----|------|
|
|
16
|
+
| `:state` | `defatom`, `atom`, `reset!`, `swap!`, `deref`, `ref?`, `add-watch`, `remove-watch`, `&atom:deref`, `&buf-list:*`, `&buffer`, `deftype-slot`, `with-type-slot` |
|
|
17
|
+
| `:io` | `read-file`, `write-file`, `get-env`, `cpu-time`, `&get-os`, `&get-calcit-*`, `generate-id!` |
|
|
18
|
+
| `:file` | `read-file`, `write-file`(与 `:io` 叠加) |
|
|
19
|
+
| `:env` | `get-env`(与 `:io` 叠加) |
|
|
20
|
+
| `:control` | `raise`, `quit!`, `try`;`assert`/`assert=`/`assert-detect`(失败时 `raise` + `eprintln`) |
|
|
21
|
+
| `:log` | `&display-stack`, `with-cpu-time`(宿主 `println`/`eprintln`/`echo` 见下节) |
|
|
22
|
+
| `:meta` | `&get-def-doc`, `&get-def-schema`, `macroexpand*`, `assert-type`, `deftype-slot`, `with-type-slot`, `&data-to-code`, `&extract-code-into-edn` |
|
|
23
|
+
| `:async` | `hint-fn` |
|
|
24
|
+
| `:watch` | `add-watch`, `remove-watch`(与 `:state` 叠加) |
|
|
25
|
+
| `:effect` | `&doseq` |
|
|
26
|
+
| `:interop` | `eval`, `js-object` |
|
|
27
|
+
|
|
28
|
+
## RegisteredProcDescriptor
|
|
29
|
+
|
|
30
|
+
`println` / `eprintln` / `echo` **不能**在 core 中用 `&runtime-implementation` 建 stub(会与 `has_def_code` 冲突);改由 descriptor 标记。
|
|
31
|
+
|
|
32
|
+
### API
|
|
33
|
+
|
|
34
|
+
- `builtins::proc_tags(["log", "io"])` — 构建 tag 集合
|
|
35
|
+
- `registered_proc_descriptor(name)` / `list_registered_procs()` / `registered_proc_has_tag(name, tag)`
|
|
36
|
+
- `cr query host-procs [--tag :log]`
|
|
37
|
+
|
|
38
|
+
### 已标记注入 proc
|
|
39
|
+
|
|
40
|
+
| Proc | Tags |
|
|
41
|
+
|------|------|
|
|
42
|
+
| `println` / `eprintln` / `echo` | `:log` `:io` |
|
|
43
|
+
| `&call-dylib-edn*` | `:interop` `:io` |
|
|
44
|
+
| `async-sleep` | `:io` |
|
|
45
|
+
| `on-control-c` | `:control` `:io` |
|
|
46
|
+
|
|
47
|
+
### 其它实现细节
|
|
48
|
+
|
|
49
|
+
- `inject_platform_apis()` 幂等;在 `main` 开头调用,保证 `cr query` 可见已注入 proc。
|
|
50
|
+
|
|
51
|
+
## 查询示例
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cr src/cirru/calcit-core.cirru query defs calcit.core --tag :state
|
|
55
|
+
cr src/cirru/calcit-core.cirru query defs calcit.core --tag :meta
|
|
56
|
+
cr calcit/test.cirru query host-procs --tag :log
|
|
57
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# `cr analyze effects-graph` Phase A MVP
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
|
|
5
|
+
实验性只读分析命令,从入口定义递归分解 State / Transform / Effect 三维信息。
|
|
6
|
+
|
|
7
|
+
## 实现
|
|
8
|
+
|
|
9
|
+
- 新模块 `src/effects_graph.rs`:`EffectsGraphAnalyzer` 遍历 `PROGRAM_CODE_DATA`,复用 call-tree 可达性模式。
|
|
10
|
+
- Tag 来源:`load_core_snapshot()` 的 `calcit.core` `:tags` + `RegisteredProcDescriptor.tags`。
|
|
11
|
+
- CLI:`cr analyze effects-graph [--root ns/def] [--format tree|json] [--detail summary|full|minimal] ...`
|
|
12
|
+
- 测试夹具:`calcit/test-effects-graph.cirru`
|
|
13
|
+
|
|
14
|
+
## 路径修正
|
|
15
|
+
|
|
16
|
+
RFC 文件名统一为 `RFCs/06-15-effects-graph-rfc.md`(原 `06-10-...` 已手动纠正)。
|
|
17
|
+
|
|
18
|
+
## 已知限制(Phase B)
|
|
19
|
+
|
|
20
|
+
- `mermaid` 输出未实现
|
|
21
|
+
- `--infer-missing` 未实现
|
|
22
|
+
- `detail full|minimal` 暂未差异化输出
|
|
23
|
+
- Respo 专用规则(`render!`、`d!`)仅靠 `!` 启发式
|
|
24
|
+
|
|
25
|
+
## 输出格式(2026-06-15 更新)
|
|
26
|
+
|
|
27
|
+
- **默认 `--format sketch`**:聚合 birdview 文本(State / Lifecycle / Effects 通道 / Data flow)
|
|
28
|
+
- 自动 `--ns-prefix` 推断为 `app.`(从入口 ns 首段)
|
|
29
|
+
- 默认 `--max-depth 2`;库代码不展开
|
|
30
|
+
- `--format mermaid` / `tree` 仍可用
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 修改记录: cr analyze weak-types 路径打印格式优化使用点号 (2026-06-12)
|
|
2
|
+
|
|
3
|
+
## 知识点与变动树
|
|
4
|
+
|
|
5
|
+
1. **Weak-type 路径打印格式优化**:
|
|
6
|
+
- 原本 `cr analyze weak-types` 命令输出 AST 节点和声明模式中的位置时会使用大量的方括号 `[` 和 `]`,如 `code[3][1][6]`。
|
|
7
|
+
- 现将其重构并统一为标准点号 (`.`) 路径分隔法(如 `code.3.1.6`),以消除视觉冗余。
|
|
8
|
+
|
|
9
|
+
2. **具体实现 & 多位置对齐**:
|
|
10
|
+
- `format_cirru_path`: 修改它的实现,将其内部的 `[idx]` 拼接机制替换成了 `.idx`,从而全局对齐了 Cirru 节点遍历的 dot 符号写法。
|
|
11
|
+
- `scan_schema_dynamic_annotation`: 内部处理 Fn 类型的索引时,把 `{path}.args[{idx}]` 和 `{path}.type-arg[{idx}]` 修改为点号连接的 `{path}.args.{idx}`、`{path}.type-arg.{idx}`,并同步修改了 `schema.args.{idx}` 语法签名位置。
|
|
12
|
+
|
|
13
|
+
3. **测试与质量验证**:
|
|
14
|
+
- 执行 `cargo test --bin cr` 通过了全部 85 项内置和回归测试(无测试报错)。
|
|
15
|
+
- 实地重新构建 `cargo build --bin cr` 并对大规模项目 `termina/msg-buffer` 完美执行 `analyze weak-types` 分析,其输出完美显示为高清晰度的 `code.6.1.3` 及 `schema.args.0.item.item.value` 点号格式。
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Calcit Type schema primitive tags support expansion
|
|
2
|
+
|
|
3
|
+
## Timestamp: 202606131200
|
|
4
|
+
|
|
5
|
+
## Modification Summary:
|
|
6
|
+
- Expanded `PRIMITIVE_SCHEMA_TAGS` inside `/Users/chenyong/repo/calcit-lang/calcit/src/snapshot.rs` to include `"record"`, `"struct"`, `"enum"`, `"trait"`, `"impl"`.
|
|
7
|
+
- This ensures schema annotations utilizing these tags (e.g., `:trait` or `:enum` in code entries) pass verification rather than raising an unrecognized primitive tag validation error.
|
|
8
|
+
- Verified with the Calcit test suite which passed 223+85 integration and unit tests without error.
|
|
9
|
+
- Updated `respo/alerts` annotations using these tags to enforce more precise typing rules in the codebase.
|