Files
l-language/docs/analysis/architecture-analysis-report-2026-06-05-0703.md
T

289 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# L Language 架构分析报告 (v0.3)
> 日期: 2026-06-05 07:03 | 自动生成 | 自上次报告后有 2 个提交
> 上次报告: [architecture-analysis-report-2026-06-05-0303.md](/D:/Code/doing_exercises/programs/L%20Language/docs/analysis/architecture-analysis-report-2026-06-05-0303.md) (基线 72a971e)
---
## 变更摘要 (自上次报告)
上次报告的 P0 #3 (for 循环 + range) 已落地。P0 #4 (struct) 仍待实施。测试大幅补强。
| Commit | 功能 | 变更量 |
|--------|------|--------|
| `8144f1b` | feat: for 循环 + range (for i in start..end) | lexer +4 Token, parser +64 |
| `382cd08` | test: sema + codegen 测试补全 | test_sema.c +5 函数, test_codegen.c +1 函数 |
10 个文件变更, +443/-6 行代码。
**核心变化**:
- 新增 3 个 Token: `TOK_FOR`, `TOK_IN`, `TOK_DOT_DOT`Token 总数 34→37
- 浮点数字面量解析修复: `peek_next` 检查 `.` 不是 `..` 时才消耗小数点
- for 循环完全通过 parser 去糖实现,无需新增 AST 节点类型或 codegen 路径
- 单元测试: 14→19 函数 (+5), 45→59 断言 (+14)
- 集成测试: 9→11 程序 (+2: `10_for_range.l`, `11_for_step2.l`)
---
## 1. 当前架构全景
### 1.1 编译流水线 (无结构变化)
```
源码(.l) -> Lexer(词法) -> Parser(语法) -> Sema(语义) -> Codegen(LLVM IR) -> Target(obj) -> GCC链接(.exe)
Token[] AstNode* 类型标注 LLVMModuleRef .o 文件
```
### 1.2 模块清单与指标
| 模块 | 文件 | 行数 | 关键职责 | 本次变更 |
|------|------|------|---------|---------|
| include/ | l_lang.h | 34 | TypeKind 枚举, 向前声明, arena_alloc_impl | — |
| util/ | arena.c(39) + .h(13) | 52 | 8MB bump allocator | — |
| lexer/ | lexer.c(141) token.c(46) + .h(40) | 227 | 手写状态机, **37** Token 类型 | +TOK_FOR/TOK_IN/TOK_DOT_DOT, peek_next 修复 |
| ast/ | ast.c(107) ast.h(93) | 200 | **15** 种节点类型 | — |
| parser/ | parser.c(405) parser.h(10) | 415 | Pratt + 递归下降 + **for 去糖** | +64 行 for 解析与去糖 |
| sema/ | sema.c(294) symbol.c(46) + .h(32) | 372 | 类型推断, 作用域链, 可变性检查 | — |
| codegen/ | codegen.c(421) target.c(30) + .h(15) | 466 | LLVM IR, 4 运行时函数 | +1 行 LLVM 22 mem2reg 注释 |
| driver/ | main.c(133) error.c(46) + .h(18) | 197 | 流水线串联, 错误报告 | — |
| test/ | test_*.c(4 文件) | 330 | 19 测试函数, 59 断言 | +6 测试函数, +14 断言 |
**总计: 23 源文件, ~1,689 行实现代码 + 251 头文件 + 330 测试 = ~2,270 行**
### 1.3 for 循环去糖路径 (新增)
这是本迭代的核心架构决策 — for 循环完全在 parser 层去糖,无下游变更:
```
for i in 0..5 { body; } (源码)
v lexer
TOK_FOR TOK_IDENT("i") TOK_IN TOK_INT_LIT(0) TOK_DOT_DOT TOK_INT_LIT(5) TOK_LBRACE ... TOK_RBRACE
v parser (desugar)
{
let mut i = 0;
while i < 5 {
body;
i = i + 1;
}
}
v sema (无变更,分析 while + let mut + assign 即可)
类型检查: i < 5 确保两边类型兼容, i = i + 1 检查可变性
v codegen (无变更,生成 while + alloca + store + load)
```
**设计评价**: 去糖策略正确。for 降级为已有原语,零 codegen/sema 入侵,零新 AST 节点。代价是步长固定为 1 — 如需自定义步长需扩展语法或使用 `for i in start..end step n`
### 1.4 技术选型评估 (更新)
| 选择 | 评价 | 最新状态 |
|------|------|---------|
| C17 + CMake + MinGW | 轻量, 学习友好 | 稳定 |
| Arena bump allocator | 零 GC 开销 | 稳定 |
| LLVM-C API 19.x | 成熟 | **LLVM 22 移除 mem2reg C API** (已记录注释) |
| 手写 Lexer/Parser | 0 外部依赖 | 37 种 Token |
| Pratt 表达式解析 | 优雅优先级 | 无变化 |
| GCC 链接 (system()) | 简单但平台绑定 | 待改进 |
| 去糖策略 (复合赋值/for) | AST 节点数不膨胀 | 已验证有效 |
---
## 2. 功能清单与成熟度
### 2.1 v0.1 基线功能
- [x] 基本类型: i64, f64, bool, void
- [x] 算术: + - * / %
- [x] 比较: == != < > <= >=
- [x] 逻辑: && || !
- [x] let 不可变变量, 类型标注 + 类型推断
- [x] 控制流: if/else (含 else if), while, return
- [x] 函数定义与调用, 递归
- [x] 内置函数: print_i64, print_f64, print_bool
- [x] 注释: // 行注释, /* */ 块注释
- [x] 错误报告: 词法/语法即时终止, 语义错误批量输出
### 2.2 v0.1+ 功能 (前两次迭代)
- [x] let mut 可变变量 + 赋值语句
- [x] 可变性检查 — 不可变变量赋值报编译错误
- [x] 字符串类型 str + 双引号字面量
- [x] print_str 内置函数
- [x] str+str 运行时拼接
- [x] 复合赋值 += -= *= /= (去糖)
- [x] LLVM 目标初始化解耦 (target.h/c)
- [x] codegen malloc -> arena 统一
### 2.3 本次迭代新增 (v0.3)
- [x] **for 循环 + range**`for i in start..end { ... }`parser 去糖为 `let mut i = start; while i < end { ...; i = i + 1; }`
- [x] **浮点数 lexer 修复**`peek_next``..``.` 冲突
- [x] **sema 测试补全** — +5 测试: let mut assign OK, immutable assign error, str type, str concat
- [x] **codegen 测试补全** — +1 测试: while 循环
- [x] **2 个新集成测试**: `10_for_range.l`, `11_for_step2.l`
- [x] LLVM 22 mem2reg 不可用注释 (防止后续困惑)
---
## 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 | **待实施** |
### 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) | ✅ 已实现 | 编译期检查 |
| 复合赋值 | ✅ 已实现 | desugar 模式 |
| for + range | ✅ 已实现 | desugar 为 while |
| 表达式 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 assign error, str, str concat | **+5 函数, +12 断言** |
| test_codegen.c | 4 | 9 | 简单函数, if/else, 二元运算, while | **+1 函数, +2 断言** |
| **合计** | **19** | **59** | | **+6 函数, +14 断言** |
### 4.2 集成测试 (11 程序)
| 文件 | 功能 | 状态 |
|------|------|------|
| 01_arithmetic.l | 算术运算 | ✅ |
| 02_if_else.l | if/else 控制流 | ✅ |
| 03_recurse.l | 递归函数 | ✅ |
| 04_fib_recursive.l | 斐波那契 | ✅ |
| 05_float.l | 浮点数 | ✅ |
| 06_mut_while.l | let mut + while | ✅ |
| 07_hello_str.l | 字符串输出 | ✅ |
| 08_str_concat.l | 字符串拼接 | ✅ |
| 09_compound_assign.l | 复合赋值 | ✅ |
| 10_for_range.l | for range 循环 | ✅ 新增 |
| 11_for_step2.l | for range (变量边界) | ✅ 新增 |
### 4.3 测试缺口
| 缺口 | 严重度 | 说明 |
|------|--------|------|
| 复合赋值无独立 desugar 测试 | 低 | 仅通过集成测试间接覆盖 |
| for 循环无独立 desugar 测试 | 低 | 同上,集成测试覆盖 |
| codegen 缺 call/str/compound/for 路径 | 中 | 4 测试仅覆盖基础路径 |
| parser 缺 for 错误恢复测试 | 低 | 缺少 for/in/.. 错误提示验证 |
---
## 5. 技术债务与风险
| # | 问题 | 状态 | 严重度 | 说明 |
|---|------|------|--------|------|
| 1 | str concat malloc 内存泄漏 | **存留** | 中 | x + y 每次 malloc 无 free,长运行程序会泄漏 |
| 2 | 复合赋值无独立 desugar 测试 | **存留** | 低 | 集成测试间接覆盖 |
| 3 | sema 层缺 str/let mut/assign 测试 | **✅ 已解决** | — | 本次新增 5 个 sema 测试 |
| 4 | codegen 测试覆盖率低 | **部分缓解** | 中 | 新增 while 测试,但 call/str/compound/for 仍无覆盖 |
| 5 | system("gcc ...") 平台绑定 | **存留** | 低 | Windows/MinGW 正常工作 |
| 6 | LLVM 22 无 mem2reg C API | **已记录** | 低 | codegen.c 注释说明需用 opt 工具 |
| 7 | 错误类型分散 (ErrorInfo + ErrorList) | **存留** | 低 | 不影响功能 |
| 8 | CHANGELOG 未更新 v0.3 | **新增** | 低 | 仍标 v0.2.0 |
---
## 6. 推荐开发路线图
### v0.4 目标 (下一迭代)
| 优先级 | 功能 | 预计工时 | 依赖/备注 |
|--------|------|---------|----------|
| **P0** | **结构体 struct** | 2-3 天 | 解锁 GEP 和复合类型,全流水线 |
| P1 | parser 测试补全 (for 错误恢复) | 0.5 天 | 回归保护 |
| P1 | codegen 测试扩展 (for/call/str) | 0.5 天 | 覆盖率补偿 |
| P1 | 更新 CHANGELOG v0.3 | 0.1 天 | 记录 for 循环 |
| P1 | str concat arena 化 (修复技术债 #1) | 0.5 天 | 替换 malloc 为 arena 分配 |
### 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) | 变化 |
|------|--------------------------|---------------------|------|
| 源文件数 | 22 | 23 | — |
| 实现代码 (.c) | 1,636 | 1,688 | +52 |
| 头文件 (.h) | 285 | 251 | -34 |
| 测试代码 | 242 | 330 | +88 |
| Token 类型 | 34 | 37 | +3 (FOR/IN/DOT_DOT) |
| AST 节点类型 | 15 | 15 | 无变化 |
| 类型系统 | 5 种 | 5 种 | 无变化 |
| 内置函数 | 4 (print_*) | 4 | 无变化 |
| C 运行时依赖 | printf, malloc, strlen, memcpy | 无变化 | — |
| 集成测试 | 9 程序 | 11 程序 | +2 |
| 单元测试函数 | 14 | 19 | +5 |
| 单元测试断言 | 45 | 59 | +14 |
| 上次 P0 完成度 | 2/4 | 3/4 (+for) | 75% |
| 上次 P0 遗留 | for, struct | struct | — |
---
*本报告由 Codex 自动生成。自上次报告 (2026-06-05 03:03) 后代码有显著变化 (2 commits, +443/-6)。P0 #3 (for 循环 + range) 完成, P0 #4 (struct) 为下一迭代唯一 P0 目标。测试覆盖从 14 函数/45 断言升至 19 函数/59 断言。*