Files
l-language/docs/analysis/architecture-analysis-report-2026-06-05-1509.md
T
Serendipity 5a0bf60698 docs: CHANGELOG v0.4/v0.5 + README/CLAUDE 版本刷新
- CHANGELOG: 新增 v0.4.0 (struct+RAII) 和 v0.5.0 (alias+enum+array+impl+match)
- README: 版本0.5.0, 测试145, 完整功能列表+运算符表
- CLAUDE: v0.5 已知限制更新
2026-06-05 18:42:24 +08:00

17 KiB
Raw Blame History

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 抽象

// 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 已实现功能 (全版本)

  • v0.1: 基本类型/算术/控制流/函数/内置函数/类型推断
  • v0.2: let mut/赋值/str/字符串拼接/复合赋值
  • v0.3: for + range
  • v0.4: struct 声明+初始化+字段访问/嵌套结构体/RAII 自动内存管理
  • 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.2v0.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) 23 天 待实施
12 模块系统 mod + use 35 天 待实施
13 泛型 (单态化) 57 天 待实施
14 枚举关联数据 (代数数据类型) 2 天 待实施
15 trait / 接口 57 天 待实施

P3: 长期

# 功能 预计工时
16 所有权 / 借用检查 24 周
17 自举 (L 编译 L) 46 周
18 标准库 (prelude) 46 周

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 程序)

  • 0111: v0.1v0.3 基线
  • 1213: struct + 嵌套 struct (v0.4)
  • 1423: 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 目标 (下一迭代, 23 天)

优先级 功能 预计工时
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) 23 天
P2 枚举关联数据 2 天
P2 AST Visitor 宏驱动 2 天

长期方向

优先级 功能 预计工时
P2 模块系统 / 泛型 / trait 各 37 天
P3 所有权 / 自举 / 标准库 26 周

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 元素类型补全、表达式作为值。