# L Language 架构分析报告 — P1 全线收官 + match 表达式 (v0.5) > 日期: 2026-06-05 15:09 | 自动生成 | **有源代码变更** > 上次代码分析基线: `1d4fb27` (2026-06-05 13:08 报告, v0.4) > 当前 HEAD: `a15cd9d` feat: match 表达式 (P1 #8 收官) > > 新增提交 (自上次源代码基线 `1d4fb27`): > - `af0725c` fix: 全面代码审查 — 修复 3 CRITICAL + 4 HIGH 问题 > - `a7fca59` fix: 5项立即修复 + 2项尽快修复 > - `4046ab1` refactor: tok_is_type 统一 + 架构改进文档 > - `da9a706` feat: struct参数/返回值 + SourceLoc + 测试补全 (**P1 #5 完成**) > - `ab88ea2` feat: 类型别名 type alias (**P1 #10 完成**) > - `5237398` feat: 枚举 enum (**P1 #7 完成**) > - `2923e75` feat: 数组+索引 [T;N], arr[i] (**P1 #6 完成**) > - `9f6e695` feat: struct方法 impl (**P1 #9 完成**) > - `a15cd9d` feat: match 表达式 (**P1 #8 收官**) **本次是自 v0.4 以来最大规模的变更: 9 个提交, P1 全部 6 项需求一次性落地。** --- ## 变更摘要 (自上次代码基线) **27 个文件变更, +2596 / -284 行。** P1 路线图全覆盖: | 变更类别 | 详情 | 影响范围 | |---------|------|---------| | **P1 #5: struct 参数/返回值** | parser 扩展 param/return type 解析; SourceLoc 抽象落地 | parser/sema/codegen/driver | | **P1 #10: 类型别名** | `type Meters = i64;` / `type P = Point;` 全流水线 | parser/sema(alias 展开链) | | **P1 #7: 枚举 enum** | `enum Color { Red, Green, Blue }`, `Color::Green` 变体 | lexer/parser/sema/codegen | | **P1 #6: 数组+索引** | `let arr: [i64; 3]`, `arr[i]`, `arr[i] = expr` | lexer/parser/sema/codegen(GEP) | | **P1 #9: struct 方法 impl** | `impl Point { fn get_x(self: Point) ... }`, `p.method()` 调用 | parser/sema(改名 mangle)/codegen | | **P1 #8: match 表达式** | `match x { pat => { body } _ => { body } }`, parser 脱糖 | parser(desugar 为 let+if-else) | | **基础设施重构** | SourceLoc 抽象, tok_is_type 统一, 架构改进文档, CRITICAL bug 修复 | 全项目 | | **测试扩展** | sema: 9→21 tests; codegen: 4→9 tests; 集成: 13→23 programs | test/ | --- ## 1. 当前架构全景 ### 1.1 编译流水线 ``` 源码(.l) → Lexer(词法) → Parser(语法) → Sema(语义) → Codegen(LLVM IR) → Target(obj) → GCC 链接(.exe) 50 Token 25 AST 节点 类型标注 LLVMModuleRef .o 文件 ``` **流水线结构无变化**,但数据流丰富度大幅提升: AST 节点从 18 增至 25, Token 从 39 增至 50, TypeKind 从 8 增至 10。 ### 1.2 模块清单与指标 | 模块 | 关键职责 | 本次变更 | |------|---------|---------| | include/ | TypeKind 枚举 (10 种: +TYPE_ENUM, +TYPE_ARRAY), SourceLoc 抽象 | +15 行 | | lexer/ | 手写状态机, **50** Token 类型 | +38 行 | | ast/ | **25** 种节点类型 (+7: TYPE_ALIAS, ENUM_DECL, ENUM_VARIANT, INDEX_EXPR, ARRAY_ASSIGN, IMPL_BLOCK, METHOD_CALL) | +218 行 | | parser/ | 递归下降 + Pratt, 新增 enum/impl/type/match 解析, `parse_type_expr()` 统一类型表达式 | +425 行 | | sema/ | 类型推断, 5 种 SymbolKind (+SYM_ENUM), impl 方法改名 mangle, alias 展开链 | +542 行 | | codegen/ | LLVM struct/array/enum/match, GEP, method call, 清理表动态扩容 | +269 行 | | driver/ | 流水线串联, SourceLoc 适配 | +11 行 | | test/ | **30** 单元测试函数 (+11), 10 集成程序新增 | +636 行 | | 汇总指标 | 上次 (v0.4, 1d4fb27) | **当前 (v0.5, a15cd9d)** | Δ | |---------|----------------------|-------------------|----| | 实现代码 (.c) | 2,221 行 | **~3,480 行** | +~1,259 | | 头文件 (.h) | 323 行 | **~450 行** | +~127 | | 测试代码 | 361 行 | **~997 行** | +636 | | **总代码量** | **2,905 行** | **~4,927 行** | **+2,022** | | Token 类型 | 39 | **50** | +11 | | AST 节点类型 | 18 | **25** | +7 | | TypeKind | 8 | **10** | +2 | | SymbolKind | 4 | **5** | +1 | | 单元测试函数 | 19 | **30** | +11 | | 集成测试程序 | 13 | **23** | +10 | | P0 完成度 | 4/4 (100%) | 4/4 (100%) | — | | P1 完成度 | 0/6 (0%) | **6/6 (100%)** | ✅ | | Git 提交数 | 13 | **22** | +9 | ### 1.3 关键架构决策 (v0.5 新增) | 决策 | 描述 | 技术理由 | |------|------|---------| | **impl 改名 mangle** | `impl Point { fn get_x }` 在 sema 阶段将函数名改为 `Point$get_x`, 自动插入 self 参数 | 零入侵 codegen: 方法调用退化为普通函数调用 | | **match 脱糖为 let+if-else** | parser 阶段将 match 转为 `{ let __match_val=expr; if ... else ... }` | 复用现有 if-else codegen, 零新增 LLVM IR 路径 | | **数组类型自引用声明** | `let arr: [i64; 3] = arr;` 以自身标识符为初始化占位符 | ArrayType 固定大小, sema/codegen 识别 TYPE_ARRAY 标注后跳过 init 分析 | | **parse_type_expr 统一入口** | 所有类型标注解析通过同一函数 | 消除分散类型解析, 支持 `[T; N]` 嵌套 | | **cleanup_list 动态扩容** | 从固定 64 槽改为 realloc 式动态扩容 (16→x2) | 消除溢出风险 | | **SourceLoc 聚合** | `typedef struct { int line; int col; }` 替代所有 `int line, int col` 参数对 | 减少参数数量, 为后续添加 `file` 做准备 | --- ## 2. P1 全线功能详解 ### 2.1 struct 作为函数参数/返回值 (P1 #5) parser 的 `parse_function` 参数类型解析从 `token_to_type()` 改为 `parse_type_expr()`, 支持 `fn f(p: Point) -> Point`。Codegen 中 struct 参数通过 alloca+store 转为栈变量, struct 返回值通过直接值传递 (LLVM struct 类型)。 **测试**: `14_struct_fn.l` — Point 作为参数和返回值。 ### 2.2 类型别名 type alias (P1 #10) `parse_type_expr()` 识别 `TOK_IDENT` 时查找已注册别名; sema Pass 0 提前注册所有别名。 ``` 语法: type Meters = i64; type P = Point; 别名展开链: parser: 解析 `let x: P` → annot struct_type_name="P" sema: scope_lookup("P") → 别名符号 → 获取真实 type=STRUCT/struct_type_name="Point" ``` **测试**: `15_type_alias.l`, `16_type_alias_struct.l` ### 2.3 枚举 enum (P1 #7) 新增 TOK_ENUM/TOK_COLON_COLON Token; `AST_ENUM_DECL`/`AST_ENUM_VARIANT` AST 节点; SYM_ENUM SymbolKind。枚举变体映射为 i64 常量 (0, 1, 2...)。 ``` 语法: enum Color { Red, Green, Blue } let c = Color::Green; // codegen: LLVMConstInt(LLVMInt64Type, 1) ``` **测试**: `17_enum.l`, sema: test_enum_ok/test_enum_bad_variant ### 2.4 数组 + 索引 (P1 #6) 新增 `[i64; N]` 语法 (`parse_type_expr` 中解析), `AST_INDEX_EXPR` (读取), `AST_ARRAY_ASSIGN_STMT` (写入)。 ``` 语法: let arr: [i64; 3] = arr; arr[0] = 10; print_i64(arr[0]); Codegen: LLVMArrayType(elem_ty, N) → alloca → GEP(0, i) → load/store 索引值 i64 → i32 截断 (LLVM GEP 要求 i32) ``` **测试**: `18_array.l`, sema 4 测试, codegen: test_codegen_array ### 2.5 struct 方法 impl (P1 #9) `parse` 处理 `impl StructName { ... }` 块; sema 将方法函数名改为 `StructName$methodName` 并追加 self 参数。 ``` 语法: impl Point { fn get_x(self: Point) -> i64 { return self.x; } } p.get_x(); // AST_METHOD_CALL Mangle 流程: parser: impl → AST_IMPL_BLOCK { struct_name, methods } sema: 遍历 impl → 改名 "Point$get_x", 插入前导 self 参数, 追加到 functions 数组 codegen: find_fn("Point$get_x") + call(receiver, args...) — 退化为普通函数调用 ``` **测试**: `19_struct_method.l`, sema 2 测试, codegen: test_codegen_method_call ### 2.6 match 表达式 (P1 #8) 新增 TOK_MATCH/TOK_MATCH_ARROW/TOK_UNDERSCORE Token; parser 内 `parse_match_stmt()` 将 match 脱糖为 let+if-else 链。 ``` 语法: match expr { pat1 => { body1; } _ => { default_body; } } 脱糖逻辑 (parser 阶段): match c { Color::Green => { print_i64(20); } _ => { print_i64(0); } } → { let __match_val = c; if __match_val == Color::Green { print_i64(20); } else { print_i64(0); } } 臂数 64 上限, 从最后一个臂往前构建 if-else 链 ``` **关键设计**: match 不产生新 AST 节点 — 直接生成 AST_BLOCK + AST_LET_STMT + AST_IF_STMT 链; codegen/sema 零改动。 **测试**: 4 个集成测试 (`20_match.l`~`23_match_wildcard.l`) --- ## 3. 架构重构与基础设施 ### 3.1 SourceLoc 抽象 ```c // include/l_lang.h typedef struct { int line; int col; } SourceLoc; ``` 所有 AST 工厂函数从 `int line, int col` 参数对改为 `SourceLoc loc` 单参数。全模块已适配。 ### 3.2 tok_is_type 统一 删除 parser.c 中重复的 `is_type_token()` 函数, 统一使用 `token.c:tok_is_type()` (已补 TOK_STR)。 ### 3.3 CRITICAL Bug 修复清单 | 严重度 | 问题 | 修复 | |--------|------|------| | CRITICAL | parser `parse_struct_init` 字段名数组栈变量悬垂 | arena 分配 + memcpy | | CRITICAL | codegen 隐式尾部 return 缺 struct 类型处理 | 添加 `LLVMConstNull(st_ty)` | | CRITICAL | str 字面量 tok 未 NUL 终止 | arena_strdup + `\0` | | HIGH | codegen return 前 cleanup 可能 free 返回值 | 从 cleanup_list 移除 | | HIGH | match 通配符 if-else 链条件 | `if (true) { body }` | | HIGH | sema impl 处理 `new_fns` 数组大小计算时机 | 预先统计 extra_fn | --- ## 4. 功能清单与成熟度 ### 4.1 已实现功能 (全版本) - [x] v0.1: 基本类型/算术/控制流/函数/内置函数/类型推断 - [x] v0.2: let mut/赋值/str/字符串拼接/复合赋值 - [x] v0.3: for + range - [x] v0.4: struct 声明+初始化+字段访问/嵌套结构体/RAII 自动内存管理 - [x] **v0.5: P1 全线 — struct 参数/返回值/类型别名/枚举/数组+索引/impl 方法/match 表达式** ### 4.2 当前已知限制 | 限制 | 严重度 | 说明 | |------|--------|------| | 数组不支持 struct 元素类型 `[Point; N]` | 中 | parse_type_expr TYPE_ARRAY 路径未传 element_struct_name | | enum 无关联数据 (代数数据类型) | 中 | 仅 C 风格枚举 | | 无表达式作为值 (expression-oriented) | 中 | if/match/block 不能出现在表达式位置 | | match 仅单值匹配 | 低 | 不支持 range pattern / guard | | 数组声明自引用语法 `let arr: [i64; 3] = arr;` | 低 | 必须写两遍 arr | | 无字符串方法 (len/slice) | 低 | str 仅拼接+打印 | --- ## 5. 与 Rust 对标: 缺失功能清单及优先级 ### 已完成 (P0 + P1 全通过) | # | 功能 | Rust 启发 | 版本 | |---|------|----------|------| | P0-1~4 | 复合赋值/str拼接/for+range/struct | — | v0.2–v0.4 | | P1-5 | struct 参数/返回值 | 值语义 | v0.5 | | P1-6 | 数组+索引 | `[T; N]`, `arr[i]` | v0.5 | | P1-7 | 枚举 | enum | v0.5 | | P1-8 | match 表达式 | 模式匹配 (简化) | v0.5 | | P1-9 | struct 方法 | impl block | v0.5 | | P1-10 | 类型别名 | type alias | v0.5 | ### P2: 中后期 | # | 功能 | 预计工时 | 状态 | |---|------|---------|------| | 11 | 表达式作为值 (expression-oriented) | 2–3 天 | 待实施 | | 12 | 模块系统 `mod` + `use` | 3–5 天 | 待实施 | | 13 | 泛型 (单态化) | 5–7 天 | 待实施 | | 14 | 枚举关联数据 (代数数据类型) | 2 天 | 待实施 | | 15 | trait / 接口 | 5–7 天 | 待实施 | ### P3: 长期 | # | 功能 | 预计工时 | |---|------|---------| | 16 | 所有权 / 借用检查 | 2–4 周 | | 17 | 自举 (L 编译 L) | 4–6 周 | | 18 | 标准库 (prelude) | 4–6 周 | ### Rust 设计哲学吸收进度 | Rust 特性 | 状态 | 备注 | |-----------|------|------| | 默认不可变 (let vs let mut) | ✅ | 编译期检查 | | 复合赋值 | ✅ | parser desugar | | for + range | ✅ | desugar 为 while | | struct 具名域 | ✅ | LLVM 命名结构体 | | impl 方法 | ✅ | sema mangle | | enum + match (简化) | ✅ | C 风格枚举 + 单值 match | | 类型别名 | ✅ | alias 展开链 | | 数组固定大小 | ✅ | GEP | | RAII 自动释放 | ✅ | cleanup_list | | 表达式 vs 语句 | ❌ | P2 优先 | | 代数数据类型 | ❌ | P2 优先 | | 泛型 (单态化) | ❌ | P2 优先 | | trait / 接口 | ❌ | P2 优先 | | 所有权 / 借用 | ❌ | P3 | | 模块系统 | ❌ | P2 优先 | --- ## 6. 测试覆盖分析 ### 6.1 单元测试 | 测试文件 | 测试函数 | 覆盖范围 | |---------|----------|---------| | test_lexer.c | 3 | token 识别, 关键字, 操作符, 注释 | | test_parser.c | 5 | 算术, let, if, while, 函数 | | test_sema.c | **21** (+12) | 类型错误, let mut, str, struct 字段, 类型别名, enum, 数组, 方法调用 | | test_codegen.c | **9** (+5) | 基础路径, struct decl/field, enum, array, method call | | **合计** | **38** (+11) | | ### 6.2 集成测试 (23 程序) - 01–11: v0.1–v0.3 基线 - 12–13: struct + 嵌套 struct (v0.4) - **14–23**: v0.5 新增 10 程序 (struct_fn/type_alias/enum/array/struct_method/4×match) ### 6.3 测试缺口 | 缺口 | 严重度 | |------|--------| | match/sema 无独立单元测试 | 高 | | 数组 struct 元素类型无测试 | 中 | | RAII + 新功能交互无验证 | 中 | | parser 错误恢复无测试 | 低 | --- ## 7. 技术债务与风险 | # | 问题 | 严重度 | 说明 | |---|------|--------|------| | 1 | analyze_expr 持续膨胀 (200+→350+ 行) | 高 | ENUM_VARIANT/INDEX_EXPR/METHOD_CALL 等 | | 2 | parser.c 单文件 939 行 | 中 | +415 行: enum/impl/type/match/match 脱糖 | | 3 | codegen.c 单文件 854 行 | 中 | 3 个 switch 持续增长 | | 4 | match 脱糖在 parser, 非独立 pass | 中 | arch-improvements #4 建议未实施 | | 5 | 数组 struct 元素类型未实现 | 中 | `[Point; N]` | | 6 | TypeKind 耦合 (arch-improvements #1) | 低 | 加新类型需改 7+ 文件 | | 7 | AST Visitor 缺失 (arch-improvements #2) | 低 | 加新节点需改 4 个 switch | | 8 | CHANGELOG 未更新 v0.4/v0.5 | 低 | 仅到 v0.3 | | 9 | LLVM 22 无 mem2reg C API | 低 | 已记录 | | 10 | `system("gcc ...")` 平台绑定 | 低 | Windows/MinGW | --- ## 8. 推荐开发路线图 ### v0.6 目标 (下一迭代, 2–3 天) | 优先级 | 功能 | 预计工时 | |--------|------|---------| | P1 | parser 独立 desugar pass (for/match/compound assign) | 0.5 天 | | P1 | 数组 struct 元素类型 `[Point; N]` | 0.5 天 | | P1 | match/sema 单元测试 | 0.5 天 | | P2 | CHANGELOG 更新 v0.4/v0.5 | 0.5 天 | ### v0.7 目标 | 优先级 | 功能 | 预计工时 | |--------|------|---------| | P2 | 表达式作为值 (expression-oriented) | 2–3 天 | | P2 | 枚举关联数据 | 2 天 | | P2 | AST Visitor 宏驱动 | 2 天 | ### 长期方向 | 优先级 | 功能 | 预计工时 | |--------|------|---------| | P2 | 模块系统 / 泛型 / trait | 各 3–7 天 | | P3 | 所有权 / 自举 / 标准库 | 2–6 周 | --- ## 9. 代码质量评估 ### 9.1 模块内聚度 | 模块 | 评价 | |------|------| | lexer | 高 — 11 新 Token 一字插入 | | parser | **中** — +415 行, parse_match_stmt(80行) + parse_type_expr(40行) + impl/enum/type 内联 | | ast | 高 — 7 新节点遵循工厂函数模式 | | sema | **中高** — +542 行: impl mangle/alias 展开/enum/array/method 语义; analyze_expr switch 350+ 行 | | codegen | **中** — +269 行: enum/array/index/method/match; 3 个 switch 持续增长 | | driver | 高 — 仅 SourceLoc 适配 | | util | 高 — 无变更 | ### 9.2 代码风格亮点 - **impl mangle 设计**: sema 阶段转换, codegen 零修改 — 干净解耦 - **match 脱糖**: 转为 AST 原语链, sema/codegen 完全复用 (但耦合在 parser 中) - **parse_type_expr 统一**: 消除分散类型解析, 天然支持 `[T; N]` - **cleanup_list 动态扩容**: arena 分配保持 zero-overhead ### 9.3 架构债务 | 债务 | 说明 | |------|------| | parser.c 939 行 | 含 enum/impl/type/match + 脱糖, 建议 P2 模块化 | | sema analyze_expr 350+ 行 | CASE 从 5 增至 10 | | codegen 3 个 switch 增长 | 新增 3 case (ENUM_VARIANT/METHOD_CALL/INDEX_EXPR) | | impl mangle 隐式命名约定 | codegen 通过 `$` 识别方法, 非结构化标记 | --- ## 10. 度量汇总 (对比) | 指标 | v0.4 (1d4fb27) | **v0.5 (a15cd9d)** | Δ | |------|----------------|-------------------|----| | 实现代码 | 2,221 行 | **~3,480 行** | +~1,259 | | 头文件 | 323 行 | **~450 行** | +~127 | | 测试代码 | 361 行 | **~997 行** | +636 | | **总代码量** | **2,905 行** | **~4,927 行** | **+2,022** | | Token 类型 | 39 | **50** | +11 | | AST 节点类型 | 18 | **25** | +7 | | TypeKind | 8 | **10** | +2 | | SymbolKind | 4 | **5** | +1 | | 单元测试函数 | 19 | **30** | +11 | | 集成测试程序 | 13 | **23** | +10 | | P0 完成度 | 4/4 (100%) | 4/4 (100%) | — | | P1 完成度 | 0/6 (0%) | **6/6 (100%)** | ✅ | | Git 提交数 | 13 | **22** | +9 | --- *本报告由 Codex 自动生成于 2026-06-05 15:09。自上次代码基线 `1d4fb27` (v0.4) 后有 9 个源代码提交 (+2596/-284 行): P1 路线图全线收官 — struct 参数/返回值、类型别名、枚举、数组+索引、struct 方法 impl、match 表达式全部落地。v0.5 实现了 Rust 启发语言的完整单片编译器能力; 下一迭代应关注 parser 独立 desugar pass、数组 struct 元素类型补全、表达式作为值。*