Files
l-language/docs/architecture-review-2026-06-07.md

182 lines
7.8 KiB
Markdown

# L Language 架构与代码审查报告
> 日期: 2026-06-07 | 全面手动审查 | HEAD: `35e2691`
## 1. 项目概览
| 指标 | 数值 |
|------|------|
| 版本 | v0.6 |
| 语言 | C17 (`-Wall -Wextra -g`) |
| 后端 | LLVM 22.x C API |
| 链接器 | clang+lld (fallback gcc) |
| 平台 | Windows 11 + MinGW-w64 |
| 总源码行数 | 5,039 (32 .c + 20 .h) |
| 单元测试 | 197 断言 (4 文件, 42 测试函数) |
| 集成测试 | 36 程序 |
| 构建警告 | **0** |
## 2. 编译流水线
```
源码(.l) → Lexer → Parser(+Desugar) → Sema → Codegen → Target → clang+lld → .exe
72 Token 27 AST 节点 类型标注 LLVM IR .o 文件 可执行文件
```
### 2.1 各阶段文件清单
| 阶段 | 文件 | 行数 | 职责 |
|------|------|------|------|
| **include/** | l_lang.h | 55 | TypeKind 枚举 (14), TypeInfo, SourceLoc |
| **lexer/** | lexer.c (180) + token.c (60) + .h (55+13) | 308 | 手写状态机, 72 Token 类型 |
| **parser/** | parser.c (564) + expr.c (484) + desugar.c (109) + parse_internal.h (71) + .h (13+30) | 1,271 | 递归下降+Pratt, 5 种去糖独立化 |
| **ast/** | ast.c (284) + ast.h (183) + visit.c (17) + visit.h (25) | 509 | 27 AST 节点 + 工厂函数 + Visitor dispatch |
| **sema/** | typeck.c (652) + sema.c (500) + symbol.c (172) + type_table.c (36) + .h (57+84+22) | 1,535 | 类型推断+检查, 泛型单态化, 数据驱动类型表 |
| **codegen/** | codegen.c (453) + cg_expr.c (440) + target.c (35) + .h (83+15+21) | 1,047 | LLVM IR 生成, 目标输出, 符号表 |
| **driver/** | main.c (232) + error.c (49) + .h (26) | 307 | 流水线串联, 错误报告 |
| **util/** | arena.c (45) + arena.h (17) | 62 | Bump allocator (8MB) |
### 2.2 文件大小分布
所有核心 .c 文件均 ≤ 652 行(限制 800):
```
typeck.c 652 ████████████████████
parser.c 564 █████████████████
sema.c 500 ████████████████
expr.c 484 ███████████████
codegen.c 453 ██████████████
cg_expr.c 440 ██████████████
```
## 3. 类型系统
### 3.1 Token 类型: 72 种
| 类别 | 数量 | 示例 |
|------|------|------|
| 关键字 | 20 | fn, let, var, if, else, while, for, in, return, guard, struct, type, enum, extend, match, pub, mod, use, trait, Self |
| 类型 | 8 | i32, i64, u64, f64, bool, char, str, void |
| 字面量 | 6 | INT_LIT, FLOAT_LIT, CHAR_LIT, true, false, STR_LIT |
| 标识符 | 2 | IDENT, UNDERSCORE |
| 算术 | 5 | + - * / % |
| 比较 | 6 | == != < > <= >= |
| 逻辑 | 4 | && \|\| \|> ! |
| 箭头 | 3 | -> to => |
| 复合赋值 | 4 | += -= *= /= |
| 括号 | 4 | ( ) { } |
| 方括号 | 2 | [ ] |
| 分隔符 | 4 | , : ; = |
| 特殊 | 4 | . :: EOF ERROR |
### 3.2 TypeKind: 14 种
- 内置: i32, i64, u64, f64, bool, char, str, void
- 复合: struct, enum, array
- 内部: GENERIC (泛型参数), UNKNOWN (未推断), ERROR (类型错误)
### 3.3 TypeTable 数据驱动
`type_table.c` 统一管理类型元数据(promote_rank, bit_width, is_signed, is_numeric),promote/can_implicit_convert/is_numeric/is_comparable 全部查表。新增类型只需在 TABLE[] 加一行。
## 4. AST 节点: 27 种
| 类别 | 节点 |
|------|------|
| 程序结构 | PROGRAM, FUNCTION, PARAMETER, BLOCK, MOD_DECL, USE_DECL |
| 语句 | LET_STMT, ASSIGN_STMT, IF_STMT, WHILE_STMT, RETURN_STMT, EXPR_STMT, ARRAY_ASSIGN_STMT |
| 表达式 | BINARY_EXPR, UNARY_EXPR, CALL_EXPR, LITERAL_EXPR, IDENT_EXPR, FIELD_ACCESS, INDEX_EXPR, METHOD_CALL |
| 类型/声明 | STRUCT_DECL, STRUCT_INIT, TYPE_ALIAS, ENUM_DECL, ENUM_VARIANT, IMPL_BLOCK, TRAIT_DECL |
新增节点流程:ast.h 加枚举 → ast.c 加工厂 → typeck.c 的 analyze_expr_init() 加一行 handler → 编译器检查未初始化的函数指针。
## 5. 已实现功能
### 5.1 P0 基础 (10 项)
基础类型 (i64/f64/bool/void), 控制流 (if/else/while/return), let/var 变量, str 类型+拼接, for..in 去糖, struct 声明+初始化+字段访问
### 5.2 P1 类型与抽象 (5 项)
type 别名, enum 声明+变体, 固定数组+索引, impl/extend 方法块, match 去糖
### 5.3 P0 扩展 (5 项)
i32/u64/char, guard 守卫, 命名参数, 管道 |>, 字符串插值
### 5.4 P2 (6 项) — 全部完成
ADT 枚举关联数据, 表达式作为值 (if-expr), if let, 模块系统 (mod), 泛型单态化, trait 接口
## 6. 测试覆盖
| 测试文件 | 函数 | 断言 | 覆盖范围 |
|----------|------|------|----------|
| test_lexer.c | 3 | 41 | 基础 token, 关键字, 运算符 |
| test_parser.c | 20 | 54 | 全语法特性 |
| test_sema.c | 24 | 74 | 类型检查, 错误检测 |
| test_codegen.c | 10 | 28 | LLVM IR 生成验证 |
| **单元合计** | **57** | **197** | |
| programs/*.l | — | 36 | 端到端集成 |
全部通过,零失败,零构建警告。
## 7. 近期重构成果
| 重构 | 效果 |
|------|------|
| parser.c 1211→564+484+109 | 表达式/语句/去糖分离 |
| sema.c 1129→500+652 | 入口/表达式检查分离 |
| codegen.c 947→453+440 | 语句/表达式生成分离 |
| desugar.c 独立化 | match/guard/for/if-let/复合赋值 5 种去糖提取 |
| TypeTable 数据驱动 | promote/convert/numeric 查表,新增类型 7→3-4 文件 |
| AST Visitor dispatch | analyze_expr switch→vtable,新增节点加一行 |
| error.c arena 化 | 消除项目唯一 malloc/realloc/strdup |
| test_parser.c 5→20 函数 | 15→54 断言,覆盖全语法特性 |
## 8. 代码质量
### 8.1 优点
- **零编译警告**: `-Wall -Wextra` 干净
- **全测试通过**: 197 单元 + 36 集成
- **内存管理统一**: 全部通过 Arena bump allocator,无散落 malloc/free(除 driver 文件读取)
- **文件大小受控**: 所有核心 .c ≤ 652 行
- **模块边界清晰**: 5 阶段流水线,内部头文件隔离实现细节
- **新增类型/节点低摩擦**: TypeTable 一行注册,Visitor 一行注册
- **去糖独立化**: 5 种语法糖从 parser 内联提取为纯函数,可独立测试
- **LLVM 22 适配**: 显式 Context 管理,CreateProcess 替代 system()
### 8.2 待改进
| # | 严重度 | 位置 | 问题 | 建议 |
|---|--------|------|------|------|
| 1 | **中** | parser/expr.c:195, parser/parser.c:497,520 | 3 处 `sprintf` 未使用 `snprintf` | 替换为 snprintf,防止标识符过长溢出 |
| 2 | **中** | parser/parser.c:535 | `use` 语句跳过解析,符号导入未实现 | 实现 use 语句的符号导入语义 |
| 3 | **低** | main.c:192 | `strcpy(p, ld_args[i])` | 用 memcpy+长度检查替代 |
| 4 | **低** | codegen/cg_expr.c | 表达式生成仍用 switch (440 行) | 后续可转为 Visitor dispatch |
| 5 | **低** | sema/typeck.c:652 | typeck.c 略超 650 行 | 泛型单态化可提取为 mono.c |
| 6 | **信息** | 全局 | 固定数组 [64]/[256] 带边界检查 | 当前均有 if (n>=N) 保护,长期可换动态分配 |
## 9. 安全审计
| 检查项 | 状态 |
|--------|------|
| 缓冲区溢出 | ✅ 全部使用 snprintf(sizeof) 或有边界检查 |
| 格式化字符串 | ✅ 无用户输入直接作为格式串 |
| 空指针解引用 | ✅ 所有 arena_alloc 返回值有 NULL 检查 |
| 内存泄漏 | ✅ Arena bump allocator 统一释放 |
| 栈溢出 | ✅ MAX_PARSE_DEPTH/MAX_CODEGEN_DEPTH 限制递归 |
| LLVM 验证 | ✅ codegen_module 调用 LLVMVerifyModule |
## 10. 架构评估
**评分: 8.5/10**
- 流水线设计清晰,每阶段独立可测试
- 近期重构显著改善模块化(文件拆分、去糖独立、数据驱动类型表)
- AST 节点新增流程标准化(枚举→工厂→handler 注册)
- 测试覆盖充足(197 单元 + 36 集成)
- 剩余问题均为中低优先级,无阻塞性缺陷
- 主要不足:codegen 表达式层仍为巨型 switch、use 语句未实现
---
*本报告手动审查生成于 2026-06-07。*