Three-inspection (structural / type / behavior) static analysis for MoonBit programs, every toolchain file kind (.mbt / .mbtx / .mbti / .mbt.md / .mbtp) and state-machine tables
Dependencies
moon add riantr/moonbit_static_analysis@0.4.1// 用途一:修订一段 MoonBit(当前子集)程序
let result : @pipeline.PipelineResult = @pipeline.run(source, "main.mbt")
println(@pipeline.render_result(result))
// 用途二:审计一台状态机(机器表以纯数据进来)
let spec : @statecheck.MachineSpec = { name: "主体", states: [...], ... }
println(@statecheck.render(spec))| 鉴 | 包 | 职责 | 产出 |
|---|---|---|---|
| 结构 | src/walk | 赋值即绑定、未用/未定义/参数被改、常量折叠剪枝 | 绑定表 fn_bindings |
| 类型 | src/types | 注解即契约、推断、赋值/实参/条件检查(声明取自绑定表) | 签名表 sigs |
| 行为 | src/interp | 格上抽象解释、按签名调度、虚栈(方法表取自签名表) | 行为发现 |
| 合并 | src/pipeline | 同一缺陷的多鉴回声 → 一条报告,lens 并集 | render_result |
moon run src/cli # demo:6 个样例 × 三鉴=== undefined.mbt ===
2:10 - error: undefined variable 'missing' (UndefinedName) [structural+type+behavior]
in main() at undefined.mbt:4
in g at undefined.mbt:1
Summary: 1 finding(s) (before merge: structural 1, type 2, behavior 1)| 鉴 | 机器侧语义 | 检查内容 |
|---|---|---|
| 结构 | 状态即绑定("赋值即绑定"推广到机器表) | 任何状态都必须被至少一条迁移绑定(出或入);只出不进 → never entered;从初始位置的可达性闭包;终点必须可达(机器必须能完成) |
| 类型 | 驱动槽契约("注解即契约") | 每个触发必须归位已知槽、无空槽;Block 必须带理由——无路必须说出口,不能沉默 |
| 行为 | 轨迹抽象执行(虚栈) | 修习历程每一步都必须有触发承载;断链的轨迹步带入口帧→出错帧的虚栈 |
let spec : @statecheck.MachineSpec = { name: "主体", states: [...], ... }
let findings : Array[@report.Report] = @statecheck.audit(spec)
let text : String = @statecheck.render(spec) // 合并后的文本报告规格 | 计数
---|---
状态 | 034
迁移 | 053
触发→槽 | 049 → 8
无路组合(带理由) | 228
修习历程 | 031 站
已知设计(4 条,出处层:设计使然——0.2.0 审计已验证):
- state '无忆' is never entered: it appears only as a transition source
- state '无筹' is never entered: it appears only as a transition source
- state '无忆' is unreachable from the initial position '立位'
- state '无筹' is unreachable from the initial position '立位'
未预期发现:**0 条**moon run src/cli 末尾那台 pyroduct 形状示例机器 是本模块内嵌的 8 状态玩具机 (statecheck.pyroduct_flavored()),不是 pyroduct 的真表;它带 182:12 这类 行:列,那是 state_span() 按状态名哈希出来的稳定伪 span(同一名字永远同一坐标), 不是任何源文件的位置——别拿它去 pyroduct 里对行号。
src/core Span/Severity/Lens/Family(merge_group 契约)/Frame
src/report Report 结构与渲染(lens 并集标签、vst 框架)
src/lexer MoonBit 词法前端
src/parser MoonBit 语法 → ast(含 .mbtx 脚本的 import 块)
src/ast MoonBit 抽象语法
src/walk 结构鉴:绑定表 + 结构发现
src/types 类型鉴:Ty/Ty?/Sig 推断
src/interp 行为鉴:AbsVal 格 + 调度 + 虚栈
src/pipeline 组装:跑三鉴 + merge_group 合并
src/moonfiles 其余文件种类:.mbt.md 逐块三鉴 / .mbti 接口审计 / .mbtp 证明 lint
src/statecheck 用途二:通用机器表审计(MachineSpec 纯数据桥)
src/samples demo 样例(内嵌 MoonBit 源)
src/cli 可执行入口(程序 demo + 文件种类 demo + 示例机器审计)| 后缀 | 本项目静态分析 |
|---|---|
| .mbt | 三鉴程序分析 |
| .mbtx | 三鉴程序分析 + 导入块审计(条目文法 "path" [@alias] [*];重复路径报 FParse;导入清单随报告回显) |
| .mbti | 接口审计:畸形行 / 重复签名 / 未知类型引用。行文法与 moon info 实际输出一致,生成文件零误报 |
| .mbt.md | literate:只分析工具链确实编译的围栏 —— mbt check / mbt test 及其 moonbit 写法;第二个词是 check 或 test 才使块成为活代码。行号对齐 .md 真实行。裸 mbt、裸 moonbit 与 nocheck 是展示块,跳过——按工具链实测,见 EXTENSIONS.md |
| .mbtp | 证明文件逻辑侧 lint(体内字符串常量、!/↔ 禁形、跨包调用、lemma 缺 proof_ensure)——不替代 moon prove |
| moon.mod / moon.pkg / workspace | 记录在案,不做静态分析(配置不是代码——官方也把两者放在 parser 的 moon_config 子包里,与 syntax / mbti_parser 并列而独立;理由见 EXTENSIONS.md「配置文件的边界」) |
moon check --target all --deny-warn # 0 错 0 警(js / native / wasm / wasm-gc)
moon test --deny-warn # 86/86 全绿(四个 target 各 86)
moon run src/cli # 程序 demo + 文件种类 demo + pyroduct 形状示例机器审计CI 只跑 --target js;上面「四个 target」是本地跑的结论,CI 不覆盖 native/wasm。
moon prove src/core --why3-config .why3.conf # 生成 19 个 VC 并交 cvc5/alt-ergo| 渠道 | 地址 |
|---|---|
| Gitee(主仓) | https://gitee.com/ren-yongxiang/moonbit_static_analysis.git |
| GitHub(镜像) | https://github.com/riantr/moonbit_static_analysis |
| mooncakes.io(包注册表) | https://mooncakes.io/docs/riantr/moonbit_static_analysis |
moonx riantr/moonbit_static_analysis@latest riantr/moonbit_doubleML@latestSCANNED 107 files under ...\ML\CI
CLEAN .mbti ...\CI/pof/pkg.generated.mbti
PARTIAL .mbt defects=2 notices=1 read up to line 36, 57 after it not shown ...\CI/pof/aggregator.mbt
12:3 - error: ... (UndefinedName) [behavior]
PARSED 32/107 files understood (29.9%); 75 more read only up to their first parse error
SUMMARY files=107 parsed=32 actionable=57 notices=211 unreliable=15759 withheld=6769 total=16027 (actionable+notices+unreliable = total; withheld ⊆ unreliable)| 目标 | 文件 | 解析 | actionable(旧 → 新) |
|---|---|---|---|
| riantr/moonbit_doubleML@latest → 0.113.0 | 180 | 73(40.5%) | 0 → 123 |
| 本仓库自身(.repos/0.3.5) | 39 | 22(56.4%) | 0 → 7 |
| moonbit_linalg_gpu | 8 | 4(50.0%) | 1 → 5 |
| ML/CI(--exclude _qa_verify) | 107 | 32(29.9%) | 11 → 57 |
与 moon check 的关系要说清楚:在 .mbt 上,本工具不与工具链的编译器 竞争——moon check 有真正的解析器和约 90 条内建告警,覆盖率恒为 100%, 实测 2.3 秒 / 128 条,且每条都带 file:line:col、源码片段与修复建议 (同一份 ML/CI 代码本工具曾报 529 条「未使用局部」,而编译器报 8 条—— 差的那 66 倍是 struct 函数体没解析)。本工具能说「编译器做不到」的地方是 .mbti / .mbt.md / .mbtp 三类文件与跨包语义。
Install
Download zipThree-inspection (structural / type / behavior) static analysis for MoonBit programs, every toolchain file kind (.mbt / .mbtx / .mbti / .mbt.md / .mbtp) and state-machine tables
Dependencies