diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bab61a..2a74836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.3.0 (2026-06-05) + +### Added +- `for` 循环 + range: `for i in start..end { ... }` (parser 去糖为 let mut + while + assign) +- `..` range 运算符 (TOK_DOT_DOT) +- 浮点数 lexer 修复:`..` 不与 `.` 冲突 +- sema 测试补全:let mut assign, immutable assign error, str type, str concat (9→21 tests) +- codegen 测试补全:while 循环 LLVMVerifyModule (7→9 tests) +- 集成测试:`10_for_range.l`、`11_for_step2.l` + +### Known Issues +- LLVM 22 C API 不支持 mem2reg pass(需用 opt 工具优化 alloca) +- str+str 运行时拼接使用 malloc(编译后程序存在泄漏,非编译器本身) + ## 0.2.0 (2026-06-05) ### Added diff --git a/docs/analysis/architecture-analysis-report-2026-06-05-0703.md b/docs/analysis/architecture-analysis-report-2026-06-05-0703.md new file mode 100644 index 0000000..f68f554 --- /dev/null +++ b/docs/analysis/architecture-analysis-report-2026-06-05-0703.md @@ -0,0 +1,288 @@ +# 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 断言。*