Files
l-language/docs/analysis/architecture-analysis-report-2026-06-05-1152.md
T
Serendipity b390d390f3 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 功能已全部完成。
2026-06-05 12:21:22 +08:00

15 KiB
Raw Blame History

L Language 架构分析报告 (v0.3 — 无代码变更)

日期: 2026-06-05 11:52 | 自动生成 | 自上次源代码基线无变更 上次代码分析基线: 382cd08 (2026-06-05 08:29 报告) 当前 HEAD: 620cec4 (CHANGELOG 更新 v0.3.0)


变更摘要 (自上次代码基线)

源代码无变更。382cd08 以来,仅有 2 个纯文档提交 (620cec4)

文件 变更 行数
CHANGELOG.md 新增 v0.3.0 条目 (for 循环 + 测试补全 + Known Issues) +14
docs/analysis/architecture-analysis-report-2026-06-05-0703.md 上一轮自动化分析报告提交 +288

结论: 编译器源代码、测试代码、构建系统均无变化。本次运行与 08:29 报告相比,唯一差异是 CHANGELOG v0.3.0 已正式提交(上次报告列为技术债 #8「CHANGELOG 未更新 v0.3」)。


1. 当前架构全景

1.1 编译流水线

源码(.l) → Lexer(词法) → Parser(语法) → Sema(语义) → Codegen(LLVM IR) → Target(obj) → GCC 链接(.exe)
              Token[]        AstNode*        类型标注         LLVMModuleRef       .o 文件

全流水线 6 个阶段,无架构变化

1.2 模块清单与指标

模块 文件 行数 关键职责
include/ l_lang.h 34 TypeKind 枚举 (7 种), 向前声明, arena_alloc_impl
util/ arena.c(39) + .h(13) 52 8MB bump allocator, strdup
lexer/ lexer.c(137) token.c(45) + .h(40) 222 手写状态机, 37 Token 类型, peek_next
ast/ ast.c(107) ast.h(93) 200 15 种节点类型, 工厂函数
parser/ parser.c(390) parser.h(10) 400 Pratt 表达式解析 + 递归下降 + for/复合赋值去糖
sema/ sema.c(294) symbol.c(46) + .h(32) 372 类型推断, 作用域链 (Scope), 可变性检查
codegen/ codegen.c(421) target.c(30) + .h(15) 466 LLVM IR 生成, 4 内置函数, 目标平台初始化
driver/ main.c(133) error.c(46) + .h(18) 197 流水线串联, CLI (l_lang <file.l> [-o <out>] [--emit-ir]), 错误报告
test/ test_*.c(4 文件) + test_utils.h(23) 353 19 测试函数, 59 断言, 11 集成程序

总计: 23 源文件, 1,688 行实现代码 + 308 行头文件 + 330 行测试 = 2,326 行

1.3 关键架构决策 (v0.2v0.3 沉淀)

决策 描述 技术理由
去糖策略 复合赋值 (+= 等) 和 for 循环在 parser 层降级为已有原语 零 codegen/sema 入侵, 零新 AST 节点, 降低维护成本
for 去糖路径 for i in 0..5 {body}let mut i=0; while i<5 {body; i=i+1;} 步长固定为 1, 如需自定义步长需扩展语法
Arena 统一分配 编译器内部所有动态内存走 arena bump allocator (8MB) 零 free 调用, 编译器结束时一次性释放
LLVM-C API 19.x 绑定 LLVM 19.x 的 C API LLVM 22 移除 mem2reg C API (已记录注释)
GCC 链接 system("gcc ...") 链接目标文件 简单但平台绑定 (Windows/MinGW)
Pratt 表达式解析 9 级优先级, 零左递归问题 比纯递归下降更优雅处理表达式

1.4 核心数据结构

Token (37 种)

关键字:    fn let mut if else while for in return
类型:      i64 f64 bool str void
字面量:    整数 浮点数 true false 字符串
运算符:    + - * / %  == != < > <= >=  && || !  -> ..  += -= *= /=
分隔符:    ( ) { }  , : ;  =
特殊:     EOF ERROR

AST 节点 (15 种)

Program  Function  Parameter  Block  LetStmt  AssignStmt  IfStmt  WhileStmt
ReturnStmt  ExprStmt  BinaryExpr  UnaryExpr  CallExpr  LiteralExpr  IdentExpr

类型系统 (7 种)

TypeKind: I64  F64  BOOL  STR  VOID  UNKNOWN  ERROR

转换规则:
  隐式: i64 → f64 (算术混合)
  显式: 函数参数/返回值必须标注
  不可转换: str ↔ 数值, bool ↔ 数值

符号表

Scope (链表栈): 全局 → 函数 → 块
  - SymbolKind: VARIABLE | PARAMETER | FUNCTION
  - 变量属性: is_mut (可变性)
  - 函数属性: return_type + param_types[] + param_count
  - 作用域退出时释放 (arena 生命周期管理)

2. 功能清单与成熟度

2.1 v0.1 基线功能 (全部完成)

  • 基本类型: i64, f64, bool, void
  • 算术: + - * / %
  • 比较: == != < > <= >=
  • 逻辑: && || !
  • let 不可变变量, 类型标注 + 类型推断
  • 控制流: if/else (含 else if), while, return
  • 函数定义与调用, 递归
  • 内置函数: print_i64, print_f64, print_bool
  • 注释: // 行注释, /* */ 块注释
  • 错误报告: 词法/语法即时终止, 语义错误批量输出

2.2 v0.2 新增功能 (全部完成)

  • let mut 可变变量 + 赋值语句
  • 可变性检查 — 不可变变量赋值报编译错误
  • 字符串类型 str + 双引号字面量
  • print_str 内置函数
  • str+str 运行时拼接 (malloc + strlen + memcpy)
  • 复合赋值 += -= *= /= (parser 去糖)
  • LLVM 目标初始化解耦 (target.h/c)
  • codegen malloc → arena 统一

2.3 v0.3 新增功能 (全部完成)

  • for 循环 + rangefor i in start..end { ... }parser 去糖
  • 浮点数 lexer 修复peek_next... 冲突
  • sema 测试补全 — +5 测试 (let mut assign, immutable error, str type, str concat)
  • codegen 测试补全 — +1 测试 (while 循环)
  • 2 个新集成测试: 10_for_range.l (0..5), 11_for_step2.l (变量边界)
  • LLVM 22 mem2reg 不可用注释
  • CHANGELOG v0.3.0 提交 (本次运行时已就绪)

3. 与 Rust 对标: 缺失功能清单及优先级

P0: 短期 (12 天/项)

# 功能 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 待实施

P0 完成度: 3/4 (75%)。struct 是解锁复合类型的最后一块 P0 拼图。

P1: 中期 (35 天/项)

# 功能 改动范围 学习价值 状态
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: 中后期 (12 周/项)

# 功能 学习价值 状态
9 模块系统 mod + use 单文件→多文件编译 待实施
10 自定义 IR 层 (三地址码/SSA) 编译器核心抽象 待实施
11 泛型 (单态化) Rust 零成本抽象基石 待实施
12 解释器模式 (walk AST) 快速验证语义 待实施

P3: 长期 (24 周/项)

# 功能 备注 状态
13 trait / 接口 需泛型 + 虚表 待实施
14 Option/Result 需泛型 + enum 待实施
15 所有权 / 借用检查 极度复杂 待实施
16 自举 (L 编译 L) 终极考验 待实施

Rust 设计哲学吸收进度

Rust 特性 状态 备注
默认不可变 (let vs let mut) 已实现 编译期检查, 可变性追踪
复合赋值 已实现 parser desugar 模式
for + range 已实现 desugar 为 while
str 拼接 已实现 运行时 malloc
表达式 vs 语句 if/match/block 作为表达式 (目前只支持语句)
模式匹配 P1 优先级
代数数据类型 需泛型
所有权 / 借用 远期

4. 测试覆盖分析

4.1 单元测试

测试文件 测试函数 断言数 覆盖范围
test_lexer.c 3 14 token 识别, 关键字, 操作符, 注释
test_parser.c 5 15 算术, let, if, while, 函数
test_sema.c 7 21 类型错误, 未定义变量, let mut, immutable error, str type, str concat
test_codegen.c 4 9 简单函数, if/else, 二元运算, while
合计 19 59

4.2 集成测试 (11 程序)

文件 功能 版本
01_arithmetic.l 算术运算 v0.1
02_if_else.l if/else 控制流 v0.1
03_recurse.l 递归函数 v0.1
04_fib_recursive.l 斐波那契 (递归) v0.1
05_float.l 浮点数 v0.1
06_mut_while.l let mut + while v0.2
07_hello_str.l 字符串输出 v0.2
08_str_concat.l 字符串拼接 v0.2
09_compound_assign.l 复合赋值 v0.2
10_for_range.l for range 循环 v0.3
11_for_step2.l for range (变量边界) v0.3

4.3 测试缺口

缺口 严重度 说明
复合赋值无独立 desugar 测试 仅通过 09_compound_assign.l 间接覆盖
for 循环无独立 desugar 测试 仅通过 10_for_range.l / 11_for_step2.l 间接覆盖
codegen 缺 call/str/compound/for 路径 4 测试仅覆盖基础路径: simple, if/else, binary, while
parser 缺 for 错误恢复测试 缺少 for/in/.. 错误提示验证
无 LLVM IR 输出一致性测试 无法检测 LLVM IR 生成回归

5. 技术债务与风险

# 问题 状态 严重度 说明
1 str concat malloc 内存泄漏 存留 x + y 每次 malloc 无 free,编译后程序运行会泄漏 (编译器自身不受影响)
2 复合赋值无独立 desugar 测试 存留 集成测试间接覆盖
3 codegen 测试覆盖率低 (4/9 路径) 存留 call/str/compound/for/return 路径无单元测试
4 system("gcc ...") 平台绑定 存留 Windows/MinGW 正常,Linux/Unix 需 gcc/cc 替换
5 LLVM 22 无 mem2reg C API 已记录 codegen.c 注释说明需用 opt 工具
6 错误类型分散 (ErrorInfo + ErrorList) 存留 不影响功能,但 API 不统一
7 CHANGELOG 未更新 v0.3 已解决 620cec4 提交了 v0.3.0 条目
8 parser.c 函数 parse_function 过长 存留 约 60 行,可拆分为多个子函数
9 无 fuzzing / 边界输入测试 新增 超大源文件、超长标识符、深层嵌套等未覆盖

风险矩阵

风险 概率 影响 缓解
LLVM API 版本升级 break 当前锁定 19.x,文档记录不兼容点
GCC 链接在非 MinGW 环境失败 可接受链接器参数或使用 LLVM lld
Arena 内存耗尽 (8MB) 极低 巨型程序才触发,编译器中止即可
str 泄漏导致大程序 OOM 短期替代方案: arena 化 str 拼接

6. 推荐开发路线图

v0.4 目标 (下一迭代)

优先级 功能 预计工时 依赖/备注
P0 结构体 struct 23 天 解锁 GEP 和复合类型,全流水线
P1 str concat arena 化 (修复技术债 #1) 0.5 天 替换 malloc 为 arena 分配
P1 codegen 测试扩展 (call/str/for) 0.5 天 覆盖率补偿
P1 parser 测试补全 (for 错误恢复) 0.5 天 回归保护

v0.5 目标

优先级 功能 预计工时
P1 数组 + 索引 2 天
P1 枚举 (C 风格) 1 天
P1 match 表达式 23 天
P1 类型别名 0.5 天

长期方向

优先级 功能 预计工时
P2 自定义 IR 层 35 天
P2 模块系统 35 天
P2 解释器模式 2 天
P3 泛型 (单态化) 57 天
P3 trait / 接口 57 天
P3 自举尝试 数周

7. 度量汇总

指标 较 v0.2 (72a971e) 较 v0.3 基线 (382cd08)
源文件数 (.c) 12 无变化
头文件数 (.h) 12 无变化
实现代码 1,688 行 +52 无变化
头文件 308 行 +23 无变化
测试代码 330 行 +88 无变化
总代码量 2,326 行 +163 无变化
Token 类型 37 +3 (FOR/IN/DOT_DOT) 无变化
AST 节点类型 15 +1 (ASSIGN_STMT) 无变化
TypeKind 7 +2 (STR, ERROR) 无变化
内置函数 4 (print_i64/f64/bool/str) +1 (print_str) 无变化
C 运行时依赖 printf, malloc, strlen, memcpy +malloc/strlen/memcpy 无变化
单元测试函数 19 +5 无变化
单元测试断言 59 +14 无变化
集成测试程序 11 +2 (for_range, for_step2) 无变化
P0 完成度 3/4 (75%) +for 无变化
P0 遗留 struct 无变化
编译产物 6 个 .exe 无变化
Git 提交数 11 +2 +1 (CHANGELOG)

8. 代码质量评估

8.1 模块内聚度

模块 内聚度 评价
lexer 纯函数接口,状态机集中在单文件,token 定义与值提取分离
parser 递归下降 + Pratt 组合清晰,去糖逻辑局部化
ast 工厂函数模式统一,union 节点设计节省内存
sema 遍历器模式,analyze_node/analyze_expr 双入口,职责明确
codegen 中高 codegen_stmt 单一大函数处理所有节点,可拆分但暂不紧急
driver main.c 串联流水线,error.c 独立,接口清晰
util 单一职责 (arena 分配器),零外部依赖

8.2 代码风格一致性

  • 蛇形命名 (snake_case) 贯穿全部源文件
  • 头文件守卫 (#ifndef X_H / #define X_H / #endif) 统一
  • 工厂函数模式 (ast_make_*) 跨 AST 模块一致
  • 错误处理模式: ErrorInfo* (即时错误) + ErrorList* (批量错误) 两类

8.3 编译警告

未在本次运行中编译,但从代码结构推断:

  • 全局变量 _tests_run / _tests_failedtest_utils.hstatic 声明 (每个翻译单元独立副本, 跨文件统计不准确)
  • Arena* 通过 void* 跨模块传递 (arena_alloc_impl(void* alloc, ...)),丢失类型安全, 但避免了模块间循环依赖

本报告由 Codex 自动生成于 2026-06-05 11:52。自上次代码基线 382cd08 后无源代码变更。当前 HEAD 620cec4 仅增加 CHANGELOG.md v0.3.0 条目 (14 行) + 上一轮分析报告 (288 行)。编译器源码、测试、构建系统均不变。P0 struct 仍为唯一待实施的 P0 功能。