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

268 lines
8.9 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.6.1
> 日期: 2026-06-06 06:53 | 自动生成 | **小幅变更**
> 上次代码基线: `de91886` (2026-06-06 00:50 报告, v0.6)
> 当前 HEAD: `031dedf` refactor: 拆分 sema analyze_expr 为 9 个辅助函数 + 调度器
> **版本: v0.6.1** (增量重构, 无功能变更)
---
## 代码变更检查
```
git log de91886..HEAD → 1 新提交, 2 文件变更, +635/-393 行
```
自 v0.6 以来仅 1 个提交, 聚焦 sema 内部重构。**无新语言特性, 无新增 Token/AST 类型**。
| # | 提交 | 类别 |
|---|------|------|
| 21 | `031dedf` refactor: 拆分 sema analyze_expr | 重构 |
**变更范围**: 仅 [sema.c](D:\Code\doing_exercises\programs\L Language\src\sema\sema.c) + 本报告。
---
## 1. 当前架构快照 (v0.6.1)
### 1.1 编译流水线
```
源码(.l) → Lexer(词法) → Parser(语法) → Sema(语义) → Codegen(LLVM IR) → Target(obj) → clang+lld 链接(.exe)
58 Token 25 AST 节点 类型标注 LLVMModuleRef .o 文件 优先 clang→fallback gcc
```
流水线拓扑未变。与 v0.6 相同。
### 1.2 模块清单与行数
| 模块 | 文件 | 行数 | vs v0.6 | 职责 |
|------|------|------|---------|------|
| include/ | l_lang.h | 55 | 0 | TypeKind (13), SourceLoc, 公共类型 |
| lexer/ | lexer.c + token.c (+ .h) | 168+53+47 = 268 | 0 | 手写状态机, 58 Token 类型 |
| ast/ | ast.c + ast.h | 221+152 = 373 | 0 | 25 种 AST 节点, 工厂函数 |
| parser/ | parser.c + parser.h | 851+10 = 861 | 0 | 递归下降+Pratt, 去糖逻辑 |
| sema/ | sema.c + symbol.c (+ .h) | **806**+148+63 = 1017 | **-65** | 类型推断, 9 个辅助函数+调度器 |
| codegen/ | codegen.c + target.c (+ .h) | 764+30+15 = 809 | 0 | LLVM IR 生成 |
| driver/ | main.c + error.c (+ .h) | 205+46+18 = 269 | 0 | 流水线串联 |
| util/ | arena.c + arena.h | 39+13 = 52 | 0 | Bump allocator (8MB) |
| **实现总计** | | **~3,735 行** | **-34 vs v0.6** | |
> sema.c: 871→806 行 (-7.5%), analyze_expr 从 ~380 行单体缩减为 15 行调度器 + 9 个独立辅助函数。
### 1.3 核心类型系统
| 枚举 | v0.6 | v0.6.1 | 变更 |
|------|------|--------|------|
| TypeKind | 13 | 13 | 0 |
| TokenKind | 58 | 58 | 0 |
| AstNodeKind | 25 | 25 | 0 |
| SymbolKind | 5 | 5 | 0 |
无新增类型。重构不涉及枚举变更。
---
## 2. 本轮重构详解: sema analyze_expr 拆分
### 2.1 问题背景
v0.6 报告中标记为技术债务 #1:
> analyze_expr 膨胀 (~380 行) | **高** | 未修复, 反而增加 | sema.c 871 行
### 2.2 拆分方案
`analyze_expr` 是一个 380+ 行的 `switch` 语句, 每种 AST 节点类型的检查逻辑直接内联。本轮重构将其拆分为:
| # | 新函数 | 行号 | 职责 |
|---|--------|------|------|
| 1 | `analyze_ident_expr` | 58 | 标识符引用类型检查 |
| 2 | `analyze_unary_expr` | 85 | 一元运算 (`-`, `!`) 类型推导 |
| 3 | `analyze_binary_expr` | 107 | 二元运算类型检查 + promote |
| 4 | `analyze_call_expr` | 220 | 函数调用参数/返回值检查 |
| 5 | `analyze_field_access` | 253 | 结构体字段访问 |
| 6 | `analyze_struct_init` | 287 | 结构体字面量初始化 |
| 7 | `analyze_enum_variant` | 333 | 枚举变体初始化 |
| 8 | `analyze_index_expr` | 352 | 数组索引 |
| 9 | `analyze_method_call` | 373 | 方法调用 (extend mangle) |
`analyze_expr` 现为 15 行调度器:
```c
static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena* a) {
switch (node->kind) {
case AST_LITERAL_EXPR: break;
case AST_IDENT_EXPR: analyze_ident_expr(node, scope, errors, a); break;
case AST_UNARY_EXPR: analyze_unary_expr(node, scope, errors, a); break;
case AST_BINARY_EXPR: analyze_binary_expr(node, scope, errors, a); break;
case AST_CALL_EXPR: analyze_call_expr(node, scope, errors, a); break;
case AST_FIELD_ACCESS: analyze_field_access(node, scope, errors, a); break;
case AST_STRUCT_INIT: analyze_struct_init(node, scope, errors, a); break;
case AST_ENUM_VARIANT: analyze_enum_variant(node, scope, errors, a); break;
case AST_INDEX_EXPR: analyze_index_expr(node, scope, errors, a); break;
case AST_METHOD_CALL: analyze_method_call(node, scope, errors, a); break;
default: break;
}
}
```
### 2.3 效果评估
| 维度 | 重构前 | 重构后 |
|------|--------|--------|
| analyze_expr 行数 | ~380 | 15 (+ 9×30-60 行辅助函数) |
| 最大函数深度 | 4 层嵌套 switch | 1 层 switch 调度 |
| 每个 AST 类型可独立修改 | 否 | 是 |
| 新增 AST 类型成本 | 改动函数中部 | 新增辅助函数 + 添加 case |
---
## 3. 功能完成度总览 (无变化)
### 3.1 P0 (v0.1-v0.4) — 100%
全 12 项保持完成状态。
### 3.2 P1 (v0.5) — 100%
全 6 项保持完成。
### 3.3 P0-扩展 (v0.6) — 100%
| # | 功能 | 状态 |
|---|------|------|
| 13 | i32 / u64 / char 类型 | ✅ |
| 14 | guard 守卫语句 | ✅ |
| 15 | 命名参数 | ✅ |
| 16 | 管道 `|>` | ✅ |
| 17 | 字符串插值 `\(expr)` | ✅ |
| 18 | extend 方法块 | ✅ |
### 3.4 语法差异化 (无变化)
| L 语法 | Rust 对应 |
|--------|----------|
| `var` | `let mut` |
| `T[N]` | `[T; N]` |
| `to` | `..` |
| `extend` | `impl` |
| `guard` | 无 (Swift 灵感) |
| `|>` | 无 (F#/Elixir 灵感) |
| `\(expr)` | 无 (Swift 灵感) |
---
## 4. Rust 对标缺失清单 (无变化)
### 4.1 已完成
共 15 项, 与 v0.6 报告相同。
### 4.2 缺失 (P2 — 中期)
| # | 功能 | 预计工时 | 优先级 | Rust 对应 |
|---|------|---------|--------|----------|
| 19 | 表达式作为值 (块返回最后表达式) | 2-3 天 | **高** | 块是表达式 |
| 20 | 枚举关联数据 (ADT) | 2-3 天 | **高** | `enum Option<T>` |
| 21 | `if let` / `while let` | 1 天 | 中 | 模式匹配简化 |
| 22 | 模块系统 `mod` + `use` | 3-5 天 | **高** | 多文件编译 |
| 23 | 泛型 (单态化) | 5-7 天 | 中 | `fn<T>(x: T)` |
| 24 | trait / 接口 | 5-7 天 | 中 | `trait`, `impl Trait` |
| 25 | 引用/切片 | 7-10 天 | 中 | `&T`, `&[T]` |
### 4.3 缺失 (P3 — 长期)
| # | 功能 | 预计工时 | Rust 对应 |
|---|------|---------|----------|
| 26 | 所有权 / 借用检查 | 2-4 周 | borrow checker |
| 27 | 闭包 (lambda) | 3-5 天 | `|x| x+1` |
| 28 | 自举 | 4-6 周 | — |
| 29 | 标准库 | 4-6 周 | std |
---
## 5. 测试覆盖 (无变化)
| 测试文件 | 测试函数 | 覆盖范围 |
|---------|----------|---------|
| test_lexer.c | 3 | token 识别 |
| test_parser.c | 5 | 语法解析基本路径 |
| test_sema.c | 24 | 类型检查 + i32/u64/char + named args + guard + pipe + 插值 |
| test_codegen.c | 10 | 代码生成 + 隐式转换 |
| **单元合计** | **42** | |
| 集成 .l 程序 | **29** | |
| **测试总计** | **71** | |
---
## 6. 代码审查
### 6.1 本轮重构评价
**正面**:
- analyze_expr 从 380+ 行缩减到 15 行调度器, 可维护性显著提升
- sema.c 总行数下降 65 行 (871→806), 净减少
- 每个 AST 类型的类型检查逻辑可独立修改/测试
- 新增 AST 类型时只需新增辅助函数 + 添加 case, 改动范围可控
**保留问题**:
- 辅助函数间仍有重复模式 (如错误格式化), 但规模不大暂不构成负担
- 辅助函数的参数签名统一 (`node, scope, errors, a`), 风格一致
### 6.2 其他无变化区域
- parser.c 仍是 851 行单文件, 去糖逻辑散落 (技术债务 #2)
- codegen.c 764 行, 未变化
- TypeKind 耦合未改善 (技术债务 #4)
- AST Visitor 缺失 (技术债务 #5)
---
## 7. 技术债务更新
### 7.1 已解决
| # | 原问题 | 解决提交 |
|---|--------|---------|
| 1 | **analyze_expr 膨胀 (~380 行)** | `031dedf` |
### 7.2 当前债务 (优先级排序)
| # | 问题 | 严重度 | 现状 |
|---|------|--------|------|
| 1 | parser.c 单文件 851 行 | **高** | 未修复 |
| 2 | 去糖无独立 pass, 错误消息受损 | **中** | 需求显现 |
| 3 | codegen.c 764 行, 仍有优化空间 | 中 | 未变化 |
| 4 | TypeKind 耦合 (改 7+ 文件) | 低 | 未修复 |
| 5 | AST Visitor 缺失 | 低 | 未修复 |
| 6 | LLVM 22 无 mem2reg C API | 低 | 平台限制 |
> 从 v0.6 报告的 7 项债务 → 6 项, analyze_expr 膨胀已解决。
---
## 8. 推荐开发路线图 (与 v0.6 一致)
### v0.7 (短期, 2-3 天)
1. **独立 desugar pass** — 将 guard/pipe/named_args 去糖从 parser 移到独立 pass
2. **枚举关联数据 (ADT)**`enum Option { Some(i64), None }`
3. **表达式作为值**`let x = if a { 1 } else { 2 }`
### v0.8 (中期, 1 周)
1. 模块系统 — `mod` + `use` + `pub`
2. `if let` / `while let`
3. 标准库起步: `io`, `convert`, `vec`
### v0.9 (中期, 1-2 周)
1. 泛型 (单态化)
2. trait / 接口
3. AST Visitor 宏驱动
---
*本报告由 Codex 自动生成于 2026-06-06 06:53。自上次代码基线 `de91886` (v0.6) 以来仅 1 个重构提交, 无功能变更。sema analyze_expr 拆分为 9+1 函数结构, 技术债务从 7 项降至 6 项。*