L Language 架构分析报告 (v0.3 — 无代码变更)
日期: 2026-06-05 11:52 | 自动生成 | 自上次源代码基线无变更
上次代码分析基线: 382cd08 (2026-06-05 08:29 报告)
当前 HEAD: 620cec4 (CHANGELOG 更新 v0.3.0)
变更摘要 (自上次代码基线)
源代码无变更。 自 382cd08 以来,仅有 2 个纯文档提交 (620cec4):
| 文件 |
变更 |
行数 |
| CHANGELOG.md |
新增 v0.3.0 条目 (for 循环 + 测试补全 + Known Issues) |
+14 |
| docs/analysis/architecture-analysis-report-2026-06-05-0703.md |
上一轮自动化分析报告提交 |
+288 |
结论: 编译器源代码、测试代码、构建系统均无变化。本次运行与 08:29 报告相比,唯一差异是 CHANGELOG v0.3.0 已正式提交(上次报告列为技术债 #8「CHANGELOG 未更新 v0.3」)。
1. 当前架构全景
1.1 编译流水线
全流水线 6 个阶段,无架构变化。
1.2 模块清单与指标
| 模块 |
文件 |
行数 |
关键职责 |
| include/ |
l_lang.h |
34 |
TypeKind 枚举 (7 种), 向前声明, arena_alloc_impl |
| util/ |
arena.c(39) + .h(13) |
52 |
8MB bump allocator, strdup |
| lexer/ |
lexer.c(137) token.c(45) + .h(40) |
222 |
手写状态机, 37 Token 类型, peek_next |
| ast/ |
ast.c(107) ast.h(93) |
200 |
15 种节点类型, 工厂函数 |
| parser/ |
parser.c(390) parser.h(10) |
400 |
Pratt 表达式解析 + 递归下降 + for/复合赋值去糖 |
| sema/ |
sema.c(294) symbol.c(46) + .h(32) |
372 |
类型推断, 作用域链 (Scope), 可变性检查 |
| codegen/ |
codegen.c(421) target.c(30) + .h(15) |
466 |
LLVM IR 生成, 4 内置函数, 目标平台初始化 |
| driver/ |
main.c(133) error.c(46) + .h(18) |
197 |
流水线串联, CLI (l_lang <file.l> [-o <out>] [--emit-ir]), 错误报告 |
| test/ |
test_*.c(4 文件) + test_utils.h(23) |
353 |
19 测试函数, 59 断言, 11 集成程序 |
总计: 23 源文件, 1,688 行实现代码 + 308 行头文件 + 330 行测试 = 2,326 行
1.3 关键架构决策 (v0.2–v0.3 沉淀)
| 决策 |
描述 |
技术理由 |
| 去糖策略 |
复合赋值 (+= 等) 和 for 循环在 parser 层降级为已有原语 |
零 codegen/sema 入侵, 零新 AST 节点, 降低维护成本 |
| for 去糖路径 |
for i in 0..5 {body} → let mut i=0; while i<5 {body; i=i+1;} |
步长固定为 1, 如需自定义步长需扩展语法 |
| Arena 统一分配 |
编译器内部所有动态内存走 arena bump allocator (8MB) |
零 free 调用, 编译器结束时一次性释放 |
| LLVM-C API 19.x |
绑定 LLVM 19.x 的 C API |
LLVM 22 移除 mem2reg C API (已记录注释) |
| GCC 链接 |
system("gcc ...") 链接目标文件 |
简单但平台绑定 (Windows/MinGW) |
| Pratt 表达式解析 |
9 级优先级, 零左递归问题 |
比纯递归下降更优雅处理表达式 |
1.4 核心数据结构
Token (37 种)
AST 节点 (15 种)
类型系统 (7 种)
符号表
2. 功能清单与成熟度
2.1 v0.1 基线功能 (全部完成)
- 基本类型: i64, f64, bool, void
- 算术: + - * / %
- 比较: == != < > <= >=
- 逻辑: && || !
- let 不可变变量, 类型标注 + 类型推断
- 控制流: if/else (含 else if), while, return
- 函数定义与调用, 递归
- 内置函数: print_i64, print_f64, print_bool
- 注释: // 行注释, /* */ 块注释
- 错误报告: 词法/语法即时终止, 语义错误批量输出
2.2 v0.2 新增功能 (全部完成)
2.3 v0.3 新增功能 (全部完成)
3. 与 Rust 对标: 缺失功能清单及优先级
P0: 短期 (1–2 天/项)
| # |
功能 |
Rust 启发 |
改动范围 |
状态 |
| 1 |
复合赋值 += -= *= /= |
复合赋值运算符 |
lexer + parser(desugar) |
✅ v0.2 |
| 2 |
str+str 运行时拼接 |
— |
codegen(malloc/strlen/memcpy) |
✅ v0.2 |
| 3 |
for 循环 + range |
for i in 0..10 {} |
lexer + parser(desugar) |
✅ v0.3 |
| 4 |
结构体 struct |
struct 具名域 + GEP |
lexer/parser/sema/codegen |
待实施 |
P0 完成度: 3/4 (75%)。struct 是解锁复合类型的最后一块 P0 拼图。
P1: 中期 (3–5 天/项)
| # |
功能 |
改动范围 |
学习价值 |
状态 |
| 5 |
数组 + 索引 [i64; N], arr[i] |
lexer/parser/sema/codegen(GEP) |
GEP 指针计算 |
待实施 |
| 6 |
枚举 (C 风格) |
lexer/parser/sema/codegen(i64) |
为代数类型铺路 |
待实施 |
| 7 |
match 表达式 |
lexer/parser/sema(穷举) + codegen |
模式匹配核心 |
待实施 |
| 8 |
类型别名 type Meters = i64 |
lexer/parser/sema(展开) |
名称等价 vs 结构等价 |
待实施 |
P2: 中后期 (1–2 周/项)
| # |
功能 |
学习价值 |
状态 |
| 9 |
模块系统 mod + use |
单文件→多文件编译 |
待实施 |
| 10 |
自定义 IR 层 (三地址码/SSA) |
编译器核心抽象 |
待实施 |
| 11 |
泛型 (单态化) |
Rust 零成本抽象基石 |
待实施 |
| 12 |
解释器模式 (walk AST) |
快速验证语义 |
待实施 |
P3: 长期 (2–4 周/项)
| # |
功能 |
备注 |
状态 |
| 13 |
trait / 接口 |
需泛型 + 虚表 |
待实施 |
| 14 |
Option/Result |
需泛型 + enum |
待实施 |
| 15 |
所有权 / 借用检查 |
极度复杂 |
待实施 |
| 16 |
自举 (L 编译 L) |
终极考验 |
待实施 |
Rust 设计哲学吸收进度
| Rust 特性 |
状态 |
备注 |
| 默认不可变 (let vs let mut) |
✅ 已实现 |
编译期检查, 可变性追踪 |
| 复合赋值 |
✅ 已实现 |
parser desugar 模式 |
| for + range |
✅ 已实现 |
desugar 为 while |
| str 拼接 |
✅ 已实现 |
运行时 malloc |
| 表达式 vs 语句 |
❌ |
if/match/block 作为表达式 (目前只支持语句) |
| 模式匹配 |
❌ |
P1 优先级 |
| 代数数据类型 |
❌ |
需泛型 |
| 所有权 / 借用 |
❌ |
远期 |
4. 测试覆盖分析
4.1 单元测试
| 测试文件 |
测试函数 |
断言数 |
覆盖范围 |
| test_lexer.c |
3 |
14 |
token 识别, 关键字, 操作符, 注释 |
| test_parser.c |
5 |
15 |
算术, let, if, while, 函数 |
| test_sema.c |
7 |
21 |
类型错误, 未定义变量, let mut, immutable error, str type, str concat |
| test_codegen.c |
4 |
9 |
简单函数, if/else, 二元运算, while |
| 合计 |
19 |
59 |
|
4.2 集成测试 (11 程序)
| 文件 |
功能 |
版本 |
| 01_arithmetic.l |
算术运算 |
v0.1 |
| 02_if_else.l |
if/else 控制流 |
v0.1 |
| 03_recurse.l |
递归函数 |
v0.1 |
| 04_fib_recursive.l |
斐波那契 (递归) |
v0.1 |
| 05_float.l |
浮点数 |
v0.1 |
| 06_mut_while.l |
let mut + while |
v0.2 |
| 07_hello_str.l |
字符串输出 |
v0.2 |
| 08_str_concat.l |
字符串拼接 |
v0.2 |
| 09_compound_assign.l |
复合赋值 |
v0.2 |
| 10_for_range.l |
for range 循环 |
v0.3 |
| 11_for_step2.l |
for range (变量边界) |
v0.3 |
4.3 测试缺口
| 缺口 |
严重度 |
说明 |
| 复合赋值无独立 desugar 测试 |
低 |
仅通过 09_compound_assign.l 间接覆盖 |
| for 循环无独立 desugar 测试 |
低 |
仅通过 10_for_range.l / 11_for_step2.l 间接覆盖 |
| codegen 缺 call/str/compound/for 路径 |
中 |
4 测试仅覆盖基础路径: simple, if/else, binary, while |
| parser 缺 for 错误恢复测试 |
低 |
缺少 for/in/.. 错误提示验证 |
| 无 LLVM IR 输出一致性测试 |
低 |
无法检测 LLVM IR 生成回归 |
5. 技术债务与风险
| # |
问题 |
状态 |
严重度 |
说明 |
| 1 |
str concat malloc 内存泄漏 |
存留 |
中 |
x + y 每次 malloc 无 free,编译后程序运行会泄漏 (编译器自身不受影响) |
| 2 |
复合赋值无独立 desugar 测试 |
存留 |
低 |
集成测试间接覆盖 |
| 3 |
codegen 测试覆盖率低 (4/9 路径) |
存留 |
中 |
call/str/compound/for/return 路径无单元测试 |
| 4 |
system("gcc ...") 平台绑定 |
存留 |
低 |
Windows/MinGW 正常,Linux/Unix 需 gcc/cc 替换 |
| 5 |
LLVM 22 无 mem2reg C API |
已记录 |
低 |
codegen.c 注释说明需用 opt 工具 |
| 6 |
错误类型分散 (ErrorInfo + ErrorList) |
存留 |
低 |
不影响功能,但 API 不统一 |
| 7 |
CHANGELOG 未更新 v0.3 |
✅ 已解决 |
— |
620cec4 提交了 v0.3.0 条目 |
| 8 |
parser.c 函数 parse_function 过长 |
存留 |
低 |
约 60 行,可拆分为多个子函数 |
| 9 |
无 fuzzing / 边界输入测试 |
新增 |
低 |
超大源文件、超长标识符、深层嵌套等未覆盖 |
风险矩阵
| 风险 |
概率 |
影响 |
缓解 |
| LLVM API 版本升级 break |
中 |
高 |
当前锁定 19.x,文档记录不兼容点 |
| GCC 链接在非 MinGW 环境失败 |
中 |
中 |
可接受链接器参数或使用 LLVM lld |
| Arena 内存耗尽 (8MB) |
极低 |
中 |
巨型程序才触发,编译器中止即可 |
| str 泄漏导致大程序 OOM |
低 |
中 |
短期替代方案: arena 化 str 拼接 |
6. 推荐开发路线图
v0.4 目标 (下一迭代)
| 优先级 |
功能 |
预计工时 |
依赖/备注 |
| P0 |
结构体 struct |
2–3 天 |
解锁 GEP 和复合类型,全流水线 |
| P1 |
str concat arena 化 (修复技术债 #1) |
0.5 天 |
替换 malloc 为 arena 分配 |
| P1 |
codegen 测试扩展 (call/str/for) |
0.5 天 |
覆盖率补偿 |
| P1 |
parser 测试补全 (for 错误恢复) |
0.5 天 |
回归保护 |
v0.5 目标
| 优先级 |
功能 |
预计工时 |
| P1 |
数组 + 索引 |
2 天 |
| P1 |
枚举 (C 风格) |
1 天 |
| P1 |
match 表达式 |
2–3 天 |
| P1 |
类型别名 |
0.5 天 |
长期方向
| 优先级 |
功能 |
预计工时 |
| P2 |
自定义 IR 层 |
3–5 天 |
| P2 |
模块系统 |
3–5 天 |
| P2 |
解释器模式 |
2 天 |
| P3 |
泛型 (单态化) |
5–7 天 |
| P3 |
trait / 接口 |
5–7 天 |
| P3 |
自举尝试 |
数周 |
7. 度量汇总
| 指标 |
值 |
较 v0.2 (72a971e) |
较 v0.3 基线 (382cd08) |
| 源文件数 (.c) |
12 |
— |
无变化 |
| 头文件数 (.h) |
12 |
— |
无变化 |
| 实现代码 |
1,688 行 |
+52 |
无变化 |
| 头文件 |
308 行 |
+23 |
无变化 |
| 测试代码 |
330 行 |
+88 |
无变化 |
| 总代码量 |
2,326 行 |
+163 |
无变化 |
| Token 类型 |
37 |
+3 (FOR/IN/DOT_DOT) |
无变化 |
| AST 节点类型 |
15 |
+1 (ASSIGN_STMT) |
无变化 |
| TypeKind |
7 |
+2 (STR, ERROR) |
无变化 |
| 内置函数 |
4 (print_i64/f64/bool/str) |
+1 (print_str) |
无变化 |
| C 运行时依赖 |
printf, malloc, strlen, memcpy |
+malloc/strlen/memcpy |
无变化 |
| 单元测试函数 |
19 |
+5 |
无变化 |
| 单元测试断言 |
59 |
+14 |
无变化 |
| 集成测试程序 |
11 |
+2 (for_range, for_step2) |
无变化 |
| P0 完成度 |
3/4 (75%) |
+for |
无变化 |
| P0 遗留 |
struct |
— |
无变化 |
| 编译产物 |
6 个 .exe |
— |
无变化 |
| Git 提交数 |
11 |
+2 |
+1 (CHANGELOG) |
8. 代码质量评估
8.1 模块内聚度
| 模块 |
内聚度 |
评价 |
| lexer |
高 |
纯函数接口,状态机集中在单文件,token 定义与值提取分离 |
| parser |
高 |
递归下降 + Pratt 组合清晰,去糖逻辑局部化 |
| ast |
高 |
工厂函数模式统一,union 节点设计节省内存 |
| sema |
高 |
遍历器模式,analyze_node/analyze_expr 双入口,职责明确 |
| codegen |
中高 |
codegen_stmt 单一大函数处理所有节点,可拆分但暂不紧急 |
| driver |
中 |
main.c 串联流水线,error.c 独立,接口清晰 |
| util |
高 |
单一职责 (arena 分配器),零外部依赖 |
8.2 代码风格一致性
- 蛇形命名 (snake_case) 贯穿全部源文件
- 头文件守卫 (
#ifndef X_H / #define X_H / #endif) 统一
- 工厂函数模式 (
ast_make_*) 跨 AST 模块一致
- 错误处理模式:
ErrorInfo* (即时错误) + ErrorList* (批量错误) 两类
8.3 编译警告
未在本次运行中编译,但从代码结构推断:
- 全局变量
_tests_run / _tests_failed 在 test_utils.h 中 static 声明 (每个翻译单元独立副本, 跨文件统计不准确)
Arena* 通过 void* 跨模块传递 (arena_alloc_impl(void* alloc, ...)),丢失类型安全, 但避免了模块间循环依赖
本报告由 Codex 自动生成于 2026-06-05 11:52。自上次代码基线 382cd08 后无源代码变更。当前 HEAD 620cec4 仅增加 CHANGELOG.md v0.3.0 条目 (14 行) + 上一轮分析报告 (288 行)。编译器源码、测试、构建系统均不变。P0 struct 仍为唯一待实施的 P0 功能。