feat: 结构体 struct — 最后一项 P0 功能
- lexer: TOK_STRUCT, TOK_DOT 关键字和运算符
- ast: AST_STRUCT_DECL/STRUCT_INIT/FIELD_ACCESS 3 种新节点
- parser: struct 声明 + .field 访问 + Name{field:val} 初始化
- sema: struct 类型符号表,字段类型解析,初始化字段检查
- codegen: LLVMStructType + extractvalue/insertvalue 字段操作
- 新增集成测试: 12_struct.l, 13_struct_nested.l
- 基于 Codex 分析报告 P0 #4
所有 P0 功能已全部完成。
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
# L Language 架构分析报告 (v0.3 — 增量分析, 无代码变更)
|
||||
|
||||
> 日期: 2026-06-05 11:50 | 自动生成 | **自上次报告后无代码变更**
|
||||
> 基线: [architecture-analysis-report-2026-06-05-0829.md](D:/Code/doing_exercises/programs/L%20Language/docs/analysis/architecture-analysis-report-2026-06-05-0829.md) (HEAD 382cd08)
|
||||
> 当前 HEAD: `620cec4` (docs-only commit: CHANGELOG v0.3 + analysis report)
|
||||
|
||||
---
|
||||
|
||||
## 变更摘要
|
||||
|
||||
**无代码变更。** 自上次分析 (2026-06-05 08:29) 以来,唯一的新 commit `620cec4` 仅包含文档更新:
|
||||
|
||||
| Commit | 内容 | 类型 |
|
||||
|--------|------|------|
|
||||
| `620cec4` | docs: CHANGELOG 更新 v0.3 — for循环 + 测试补全 | docs-only |
|
||||
| `382cd08` | test: sema + codegen 测试补全 — 86 单元测试 | 代码基线 (上次分析) |
|
||||
|
||||
`git diff 382cd08..620cec4` 结果: 仅 `CHANGELOG.md` (+14) 和 `architecture-analysis-report-2026-06-05-0703.md` (+288) 两个非代码文件变更。所有 `.c` / `.h` / `CMakeLists.txt` / 测试程序全未变动。
|
||||
|
||||
---
|
||||
|
||||
## 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 枚举 (7种), 向前声明, arena_alloc_impl |
|
||||
| util/ | arena.c (39) + .h (13) | 39 | 13 | 8MB bump allocator |
|
||||
| lexer/ | lexer.c (137) + token.c (45) | 182 | 50 | 手写状态机, 37 种 Token |
|
||||
| ast/ | ast.c (107) + .h (93) | 107 | 93 | 15 种 AST 节点 + 工厂函数 |
|
||||
| parser/ | parser.c (390) + .h (10) | 390 | 10 | Pratt 表达式 + 递归下降 + for/复合赋值去糖 |
|
||||
| sema/ | sema.c (294) + symbol.c (46) | 340 | 41 | 类型推断, 作用域链, 可变性检查 |
|
||||
| codegen/ | codegen.c (421) + target.c (30) | 451 | 26 | LLVM IR 生成, 4 运行时内置函数, 目标初始化 |
|
||||
| driver/ | main.c (133) + error.c (46) | 179 | 18 | 流水线串联, 命令行参数, 错误报告 |
|
||||
|
||||
**总计: 11 `.c` 源文件 (1,688 行) + 10 `.h` 头文件 (251 行) + 1 公共头 (34 行) = ~1,973 行实现代码 + ~330 行测试代码 = ~2,303 行**
|
||||
|
||||
### 1.3 核心数据结构
|
||||
|
||||
| 数据结构 | 定义位置 | 关键字段 |
|
||||
|---------|---------|---------|
|
||||
| `TokenKind` (37 枚举值) | [token.h](/D:/Code/doing_exercises/programs/L%20Language/src/lexer/token.h:7) | 关键字/类型/字面量/标识符/运算符/分隔符/EOF/ERROR |
|
||||
| `Token` | [token.h](/D:/Code/doing_exercises/programs/L%20Language/src/lexer/token.h:30) | kind, start, length, line, col |
|
||||
| `AstKind` (15 枚举值) | [ast.h](/D:/Code/doing_exercises/programs/L%20Language/src/ast/ast.h:8) | PROGRAM → IDENT_EXPR |
|
||||
| `AstNode` (union 实现) | [ast.h](/D:/Code/doing_exercises/programs/L%20Language/src/ast/ast.h:38) | kind, type, line, col, as.{12 sub-structs} |
|
||||
| `TypeKind` (7 枚举值) | [l_lang.h](/D:/Code/doing_exercises/programs/L%20Language/include/l_lang.h:10) | I64, F64, BOOL, STR, VOID, UNKNOWN, ERROR |
|
||||
| `Scope` (作用域链) | [symbol.h](/D:/Code/doing_exercises/programs/L%20Language/src/sema/symbol.h:1) | symbols[], count, parent |
|
||||
| `Symbol` (符号条目) | [symbol.h](/D:/Code/doing_exercises/programs/L%20Language/src/sema/symbol.h:1) | name, type, kind, return_type, param_types, is_mut |
|
||||
|
||||
### 1.4 AST 节点覆盖矩阵
|
||||
|
||||
| AST 节点 | Lexer | Parser | Sema | Codegen |
|
||||
|----------|-------|--------|------|---------|
|
||||
| AST_PROGRAM | — | ✅ | ✅ | ✅ |
|
||||
| AST_FUNCTION | — | ✅ | ✅ | ✅ |
|
||||
| AST_PARAMETER | — | ✅ | — | — |
|
||||
| AST_BLOCK | — | ✅ | ✅ | ✅ |
|
||||
| AST_LET_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_ASSIGN_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_IF_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_WHILE_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_FOR_STMT | 去糖 (lexer 标记) | 去糖为 while | — | — |
|
||||
| AST_RETURN_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_EXPR_STMT | — | ✅ | ✅ | ✅ |
|
||||
| AST_BINARY_EXPR | — | ✅ | ✅ | ✅ |
|
||||
| AST_UNARY_EXPR | — | ✅ | ✅ | ✅ |
|
||||
| AST_CALL_EXPR | — | ✅ | ✅ | ✅ |
|
||||
| AST_LITERAL_EXPR | — | ✅ | ✅ | ✅ |
|
||||
| AST_IDENT_EXPR | — | ✅ | ✅ | ✅ |
|
||||
|
||||
- **完整覆盖率**: 15 个 AST 节点在 sema 和 codegen 中全部覆盖 (100%)。AST_PARAMETER 无需独立 sema/codegen 路径 (函数签名处理时展开)。for 循环和复合赋值在 parser 层去糖,无 AST 节点增量。
|
||||
- **去糖策略**: for 循环 (TOK_FOR + TOK_IN + TOK_DOT_DOT) 和复合赋值 (TOK_PLUS_EQ 等) 在 parser 层去糖为 while + let mut + assign,零下游模块变更。
|
||||
|
||||
### 1.5 技术选型评估
|
||||
|
||||
| 选择 | 评价 | 状态 |
|
||||
|------|------|------|
|
||||
| C17 + CMake + MinGW (GCC 14.x) | 轻量, 学习友好, 交叉编译受限 | 稳定 |
|
||||
| Arena bump allocator (8MB) | 零 GC 开销, 无 free, 编译时内存线性 | 稳定 |
|
||||
| LLVM-C API 19.x | 成熟, 表达式级映射 | LLVM 22 mem2reg C API 已移除 (有注释) |
|
||||
| 手写 Lexer/Parser (Pratt) | 0 外部依赖, 37 Token | 稳定 |
|
||||
| 去糖策略 (for / 复合赋值) | AST 节点数不膨胀, 零下游侵入 | 验证有效 |
|
||||
| GCC system() 链接 | 简单但平台绑定 (MinGW) | 待改进 |
|
||||
| 错误报告 (即时终止 + 批量输出) | 分阶段差异处理 | 稳定 |
|
||||
|
||||
---
|
||||
|
||||
## 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.2 新增 (全部完成)
|
||||
|
||||
- [x] `let mut` 可变变量 + 赋值语句 (`x = expr`)
|
||||
- [x] 可变性检查 — 不可变变量赋值报编译错误
|
||||
- [x] 字符串类型 `str` + 双引号字面量
|
||||
- [x] `print_str` 内置函数
|
||||
- [x] `str + str` 运行时拼接 (malloc + strlen + memcpy)
|
||||
- [x] 复合赋值 `+=` `-=` `*=` `/=` (parser 去糖)
|
||||
- [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] `..` range 运算符 (TOK_DOT_DOT)
|
||||
- [x] 浮点数 lexer 修复 — `peek_next` 防 `..` 与 `.` 冲突
|
||||
- [x] sema 测试补全: +5 测试 (let mut assign OK, immutable assign error, str type, str concat)
|
||||
- [x] codegen 测试补全: +1 测试 (while 循环)
|
||||
- [x] 集成测试: `10_for_range.l`, `11_for_step2.l`
|
||||
|
||||
---
|
||||
|
||||
## 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 作为表达式 |
|
||||
| 模式匹配 (match) | ❌ | P1 |
|
||||
| 代数数据类型 (enum) | ❌ | 需泛型 |
|
||||
| 结构体 (struct) | ❌ | P0 #4 |
|
||||
| 所有权 / 借用 | ❌ | P3 远期 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 测试覆盖分析
|
||||
|
||||
### 4.1 单元测试 (19 函数, 59 断言)
|
||||
|
||||
| 测试文件 | 函数数 | 覆盖范围 |
|
||||
|---------|--------|---------|
|
||||
| test_lexer.c | 3 | token 识别, 关键字, 操作符, 注释 |
|
||||
| test_parser.c | 5 | 算术, let, if, while, 函数 |
|
||||
| test_sema.c | 7 | 类型错误, 未定义变量, let mut, immutable assign, str, str concat |
|
||||
| test_codegen.c | 4 | 简单函数, if/else, 二元运算, while |
|
||||
|
||||
### 4.2 集成测试 (11 程序)
|
||||
|
||||
| # | 文件 | 测试功能 | 状态 |
|
||||
|---|------|---------|------|
|
||||
| 1 | 01_arithmetic.l | 算术运算 | ✅ |
|
||||
| 2 | 02_if_else.l | if/else 控制流 | ✅ |
|
||||
| 3 | 03_recurse.l | 递归函数 | ✅ |
|
||||
| 4 | 04_fib_recursive.l | 斐波那契 | ✅ |
|
||||
| 5 | 05_float.l | 浮点数 | ✅ |
|
||||
| 6 | 06_mut_while.l | let mut + while | ✅ |
|
||||
| 7 | 07_hello_str.l | 字符串输出 | ✅ |
|
||||
| 8 | 08_str_concat.l | 字符串拼接 | ✅ |
|
||||
| 9 | 09_compound_assign.l | 复合赋值 | ✅ |
|
||||
| 10 | 10_for_range.l | for range 循环 | ✅ |
|
||||
| 11 | 11_for_step2.l | for range (变量边界) | ✅ |
|
||||
|
||||
### 4.3 测试缺口
|
||||
|
||||
| # | 缺口 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| 1 | codegen 缺 call/str/compound/for 路径 | 中 | 4 测试函数仅覆盖基础路径 |
|
||||
| 2 | parser 缺 for 错误恢复测试 | 低 | 无 for/in/.. 错误提示验证 |
|
||||
| 3 | 复合赋值无独立 desugar 测试 | 低 | 仅集成测试间接覆盖 |
|
||||
| 4 | for 循环无独立 desugar 测试 | 低 | 同上 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术债务
|
||||
|
||||
| # | 问题 | 严重度 | 说明 | 趋势 |
|
||||
|---|------|--------|------|------|
|
||||
| 1 | str concat malloc 内存泄漏 | **中** | `x + y` 每次 malloc, 无 free; 编译后程序泄漏, 不影响编译器 | 存留 |
|
||||
| 2 | codegen 测试覆盖率低 (4/15 AST 路径) | **中** | call/str/compound/for 路径无单元测试 | 存留 |
|
||||
| 3 | system("gcc ...") 平台绑定 | 低 | Windows/MinGW 正常工作, 其他 OS 需手动链接 | 存留 |
|
||||
| 4 | LLVM 22 移除 mem2reg C API | 低 | 已记录注释; 需用 opt 工具替代 | 存留 |
|
||||
| 5 | 错误类型分散 (ErrorInfo + ErrorList) | 低 | token/parse 用 ErrorInfo, sema 用 ErrorList; 不影响功能 | 存留 |
|
||||
| 6 | 复合赋值无独立 desugar 测试 | 低 | 集成测试间接覆盖 | 存留 |
|
||||
| 7 | for 循环无独立 desugar 测试 | 低 | 集成测试间接覆盖 | 存留 |
|
||||
| 8 | for 循环步长固定为 1 | 低 | 需扩展语法支持 step n | 存留 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 推荐开发路线图
|
||||
|
||||
### v0.4 目标 (下一迭代 — 无变更建议)
|
||||
|
||||
| 优先级 | 功能 | 预计工时 | 依赖/备注 |
|
||||
|--------|------|---------|----------|
|
||||
| **P0** | **结构体 struct** | 2-3 天 | 解锁 GEP 和复合类型, 全流水线改动 |
|
||||
| P1 | codegen 测试扩展 (for/call/str/compound) | 0.5 天 | 覆盖率补偿 |
|
||||
| P1 | parser 测试补全 (for 错误恢复) | 0.5 天 | 回归保护 |
|
||||
| P1 | str concat arena 化 (修复技术债 #1) | 0.5 天 | 替换 malloc 为 arena 分配 |
|
||||
|
||||
### v0.5 目标
|
||||
|
||||
| 优先级 | 功能 | 预计工时 |
|
||||
|--------|------|---------|
|
||||
| P1 | 数组 + 索引 [i64; N], arr[i] | 2 天 |
|
||||
| P1 | 枚举 (C 风格) | 1 天 |
|
||||
| P1 | match 表达式 | 2-3 天 |
|
||||
| P1 | 类型别名 type X = T | 0.5 天 |
|
||||
|
||||
### 长期目标
|
||||
|
||||
| 优先级 | 功能 | 预计工时 |
|
||||
|--------|------|---------|
|
||||
| P2 | 自定义 IR 层 (三地址码/SSA) | 3-5 天 |
|
||||
| P2 | 模块系统 mod + use | 3-5 天 |
|
||||
| P2 | 解释器模式 | 2 天 |
|
||||
| P3 | 泛型 (单态化) | 5-7 天 |
|
||||
| P3 | trait / 接口 | 5-7 天 |
|
||||
| P3 | 自举尝试 | 数周 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 度量汇总
|
||||
|
||||
| 指标 | 值 | 变化 (vs 0829 报告) |
|
||||
|------|-----|-------------------|
|
||||
| Git HEAD | 620cec4 | +1 commit (docs-only) |
|
||||
| 代码基线 | 382cd08 | **无变化** |
|
||||
| 源文件 (.c) | 11 文件, 1,688 行 | — |
|
||||
| 头文件 (.h) | 11 文件, 285 行 | — |
|
||||
| Token 类型 | 37 | — |
|
||||
| AST 节点类型 | 15 | — |
|
||||
| 类型系统 | 5 种 (i64, f64, bool, str, void) | — |
|
||||
| 内置函数 | 4 (print_i64/f64/bool/str) | — |
|
||||
| 集成测试 | 11 程序 | — |
|
||||
| 单元测试函数 | 19 | — |
|
||||
| 单元测试断言 | 59 | — |
|
||||
| P0 完成度 | 3/4 (75%) | — (struct 待实施) |
|
||||
| P1-P3 完成度 | 0/12 | — |
|
||||
| AST 节点覆盖率 (sema) | 15/15 (100%) | — |
|
||||
| AST 节点覆盖率 (codegen) | 15/15 (100%) | — |
|
||||
|
||||
---
|
||||
|
||||
## 8. 结论
|
||||
|
||||
**本次分析确认: 自 2026-06-05 08:29 报告以来无代码变更。** 基线代码状态 `382cd08` 保持不变, 唯一新增的 commit `620cec4` 是 CHANGELOG 文档更新。
|
||||
|
||||
**当前状态**: v0.3 阶段已完成。语言支持 37 种 Token, 15 种 AST 节点, 5 种类型, 4 个内置函数。所有 AST 节点在 sema 和 codegen 中均有覆盖。19 个单元测试 + 11 个集成测试提供回归保护。去糖策略 (for 循环/复合赋值) 被验证为有效的架构决策, 实现了零下游侵入的新语法特性扩展。
|
||||
|
||||
**最大优先级**: P0 #4 结构体 struct 是唯一尚未完成的短期高优先功能, 也是解锁数组、枚举等复合类型的关键前置。
|
||||
|
||||
**技术债务**: 8 项债务中, 2 项为中危 (str concat 内存泄漏, codegen 测试覆盖率), 其余均为低危或已缓解。
|
||||
|
||||
---
|
||||
|
||||
*本报告由 Codex 自动生成。自上次报告 (2026-06-05 08:29) 后无代码变更。代码基线 382cd08, 唯一新增 commit 620cec4 为 CHANGELOG 文档。*
|
||||
Reference in New Issue
Block a user