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

13 KiB
Raw Blame History

L Language 架构分析报告 v0.6

日期: 2026-06-06 00:50 | 自动生成 | 重大代码变更 上次代码基线: a15cd9d (2026-06-05 17:08 报告, v0.5) 当前 HEAD: de91886 fix: CreateProcess 替代 system() 调 ld.lld,消除 shell 转义问题 版本: v0.6


代码变更检查

git log a15cd9d..HEAD → 20 新提交, 36 文件变更, +2483/-163 行

自 v0.5 以来累计 20 个提交,涵盖 6 个新语言特性、语法差异化调整、链接器重构、安装包系统。

详细提交链:

# 提交 类别
1-2 CHANGELOG/语言参考文档 文档
3-4 CLAUDE.md 语言设计哲学 文档
5 数组初始化 = arr 语法说明 文档
6 match/sema 单元测试 (145→158) 测试
7 数组支持 struct 元素类型 Point[N] P1-5 修复
8 测试计数更新 145→158 + 23→24 测试
9 for..in 范围语法 ..to 语法差异化
10 let mutvar 语法差异化
11 [T; N]T[N] 后置语法 语法差异化
12 implextend 语法差异化
13 新增 i32/u64/char 类型 + 字符字面量 新功能
14 guard 语句 新功能
15 命名参数 新功能
16 管道 ` >+ 字符串插值(expr)` — P0 四特性收官
17 README/CHANGELOG/语言参考更新至 v0.6 文档
18 链接器 gcc → clang + lld 基础设施
19 NSIS 安装包脚本 基础设施
20 CreateProcess 替代 system() 调 ld.lld 基础设施

1. 当前架构快照 (v0.6)

1.1 编译流水线

源码(.l) → Lexer(词法) → Parser(语法) → Sema(语义) → Codegen(LLVM IR) → Target(obj) → clang+lld 链接(.exe)
            58 Token      25 AST 节点      类型标注     LLVMModuleRef       .o 文件        优先 clang→fallback gcc

v0.5 的 GCC 链接器已被 clang + lld 替代(自动 fallback)。system() 调用被 CreateProcess 替代,消除 shell 转义问题。

1.2 模块清单与行数

模块 文件 行数 vs v0.5 职责
include/ l_lang.h 55 -2 TypeKind (13), SourceLoc, 公共类型
lexer/ lexer.c + token.c (+ .h) 168+53+47 = 268 +11 手写状态机, 58 Token 类型
ast/ ast.c + ast.h 221+152 = 373 -31 25 种 AST 节点, 工厂函数 (arg_names 扩展)
parser/ parser.c + parser.h 851+10 = 861 +23 递归下降+Pratt, guard/pipe/插值去糖
sema/ sema.c + symbol.c (+ .h) 871+148+63 = 1082 +77 类型推断, can_implicit_convert, 命名参数重排
codegen/ codegen.c + target.c (+ .h) 764+30+15 = 809 -55 LLVM IR 生成, coerce_int 隐式转换
driver/ main.c + error.c (+ .h) 205+46+18 = 269 +58 流水线串联, CreateProcess 链接
util/ arena.c + arena.h 39+13 = 52 不变 Bump allocator (8MB)
实现总计 ~3,769 行 +434 vs v0.5

注意: codegen.c 从 824 行收缩到 764 行(-7.3%),说明新加入的 pipe/guard/插值等功能去糖后不需要 codegen 层改动。

1.3 核心类型系统变化

枚举 v0.5 v0.6 变更
TypeKind 10 13 +TYPE_I32, TYPE_U64, TYPE_CHAR
TokenKind 50 58 +TOK_VAR, TOK_GUARD, TOK_I32, TOK_U64, TOK_CHAR, TOK_CHAR_LIT, TOK_PIPE, TOK_TO; TOK_IMPL→TOK_EXTEND
AstNodeKind 25 25 不变 — 所有新功能经去糖复用现有节点
SymbolKind 5 5 不变

TypeKind 完整列表: TYPE_I32, TYPE_I64, TYPE_U64, TYPE_F64, TYPE_BOOL, TYPE_CHAR, TYPE_STR, TYPE_VOID, TYPE_STRUCT, TYPE_ENUM, TYPE_ARRAY, TYPE_UNKNOWN, TYPE_ERROR

Token 新增:

新增 Token 用途
TOK_VAR var 关键字 (替代 let mut)
TOK_GUARD guard 关键字
TOK_I32 / TOK_U64 / TOK_CHAR 新基本类型
TOK_CHAR_LIT 字符字面量 '"'"'A'"'"'
TOK_PIPE 管道运算符 `
TOK_TO 范围运算符 to (替代 ..)
TOK_EXTEND extend 关键字 (替代 impl)

AST 结构体扩展:

  • AST_CALL_EXPR.call 新增 arg_names 字段 — 支持命名参数
  • AST_METHOD_CALL.method_call 新增 arg_names 字段 — 支持命名参数
  • AST_LITERAL_EXPR.literal 新增 lit_type + union 扩展 — 支持 char 字面量

Symbol 扩展:

  • Symbol.param_names 新增 — 支持命名参数匹配

2. 功能完成度总览

2.1 P0 (v0.1-v0.4) — 100%

全 12 项保持完成状态。

2.2 P1 (v0.5) — 100%

全 6 项保持完成,P1-5 (数组 struct 元素类型) 在本轮修复。

2.3 P0-扩展 (v0.6 新增) — 100%

# 功能 去糖策略 灵感来源 影响层
13 i32 / u64 / char 类型 TypeKind 扩展 + can_implicit_convert Rust/ML lexer/ast/sema/codegen
14 guard x >= 0 else { return -1; } parser 去糖为 if-else Swift parser
15 draw_rect(width: 10, height: 20) sema 重排序为位置参数 Python/Swift parser/sema
16 `10 > double() > add(5)` parser 去糖为 add(double(10), 5)
17 "Hello, \(name)!" lexer+parser 去糖为 str+str Swift/Rust lexer/parser
18 extend 方法块 即原 impl mangle,改名 差异化 lexer

2.4 语法差异化 (L 语言独有)

L 语法 Rust 对应 理由
var let mut 更简洁,2 字符 vs 6 字符
T[N] [T; N] C 风格直觉,减少括号
to .. 明确语义 (省略终值 to vs 闭区间 ..=)
extend impl 避免 Rust 预留词
guard 无直接对应 Swift 灵感,前条件守卫
` >` 无直接对应
\(expr) 无直接对应 Swift 风格字符串插值

3. Rust 对标缺失清单

3.1 已完成

特性 状态 版本
默认不可变 (let) / 可变 (var) v0.1-v0.6
复合赋值 v0.2
for + range v0.3
struct 具名域 v0.4
impl/extend 方法 v0.5
enum + match v0.5
类型别名 v0.5
数组固定大小 v0.5
数组 struct 元素类型 v0.6
RAII 自动释放 v0.4
命名参数 v0.6
管道运算符 v0.6
字符串插值 v0.6
guard 守卫语句 v0.6
i32/u64/char 多种整数类型 v0.6

3.2 缺失 (P2 — 中期, 按难度排序)

# 功能 预计工时 优先级 Rust 对应 说明
19 表达式作为值 (块返回最后表达式) 2-3 天 块是表达式 sema/codegen 需处理块类型推断, 当前 block→void
20 枚举关联数据 (ADT) 2-3 天 enum Option<T> 当前仅简单常量枚举, 需 payload + 模式匹配扩展
21 if let / while let 1 天 if let Some(x) = opt 基于枚举关联数据
22 模块系统 mod + use 3-5 天 mod, use, pub 多文件编译, 符号可见性
23 泛型 (单态化) 5-7 天 fn<T>(x: T) sema 类型参数收集, codegen 复制
24 trait / 接口 5-7 天 trait, impl Trait vtable 或单态化分派
25 引用/切片 7-10 天 &T, &[T] 需指针层次, 生命周期标注

3.3 缺失 (P3 — 长期)

# 功能 预计工时 Rust 对应
26 所有权 / 借用检查 2-4 周 borrow checker
27 闭包 (lambda) 3-5 天 `
28 自举 (L 编译 L) 4-6 周
29 标准库 (prelude) 4-6 周 std

4. 测试覆盖

测试文件 测试函数 vs v0.5 覆盖范围
test_lexer.c 3 不变 token 识别
test_parser.c 5 不变 语法解析基本路径
test_sema.c 24 +3 i32/u64/char 转换, named args, guard, 管道, 插值
test_codegen.c 10 +1 隐式转换, 命名参数, i32/u64/char codegen
单元合计 42 +4
集成 .l 程序 29 +6 24_array_struct, 25_new_types, 26_guard, 27_named_args, 28_pipe, 29_interp
测试总计 71 +10

新集成测试覆盖:

  • 24_array_struct.l — struct 数组 (P1-5 修复验证)
  • 25_new_types.l — i32/u64/char 类型 + 隐式转换
  • 26_guard.l — guard 守卫语句
  • 27_named_args.l — 命名参数任意顺序
  • 28_pipe.l — 管道 |> 函数组合
  • 29_interp.l — 字符串插值

5. 代码审查 — 风险区域

5.1 去糖策略的评价

v0.6 延续了 v0.5 的去糖哲学: pipe/guard/插值/named_args 全在 parser 层去糖为现有 AST 节点。优势是 sema/codegen 改动极小(codegen 甚至缩水 60 行),但代价是:

  1. parser.c 进一步膨胀: 825→851 行,去糖逻辑散落在 parse_exprparse_statement 之间
  2. 错误消息质量下降: 去糖后生成的 AST 丢失原始语法信息,错误报告指向去糖后的 if-else 而非原始 guard 语句
  3. 调试/IR 可读性: 用户写 10 |> double() 但 IR 中看到的是 double(10),不利于学习

建议: v0.7 考虑将 guard/match/named_args/pipe 去糖抽取为独立 desugar pass,在 parser 生成 AST 之后、sema 之前运行。这既能保持"去糖"优势,又能改善错误消息质量。

5.2 sema.c 持续膨胀

sema.c 从 809→871 行 (v0.5→v0.6)analyze_expr 仍然是单函数怪兽 (~380 行)。新增的 can_implicit_convert() 是好的模块化进步,但类型检查逻辑仍需拆分。

5.3 TypeKind 耦合未改善

TypeKind 从 10 增加到 13,修改范围涉及 7+ 文件。加新类型仍是全局搜索替换作业。

5.4 链接器变更风险

gcc→clang+lld 变更是正确方向,但 fallback 链 (clang→gcc) 增加了 CI 配置复杂度。自包含安装包 (39MB) 和 NSIS 安装包 (62MB) 是两个并行方案,后续需统一。


6. 技术债务更新

6.1 已解决

# 原问题 解决提交
5 数组 struct 元素类型 [Point; N] 未实现 a45f7d8
6 match/sema 无独立单元测试 beac40f
9 CHANGELOG 未更新 v0.4/v0.5 5a0bf60 + 2baf762

6.2 当前债务 (优先级排序)

# 问题 严重度 现状 备注
1 analyze_expr 膨胀 (~380 行) 未修复, 反而增加 sema.c 871 行, +62 vs v0.5
2 parser.c 单文件 851 行 未修复, +26 行 去糖逻辑散落
3 去糖无独立 pass, 错误消息受损 需求显现 v0.6 新暴露
4 codegen.c 824→764 行, 但仍有优化空间 改善中 struct/element_type 逻辑可精简
5 TypeKind 耦合 (改 7+ 文件) 未修复 13 种类型, 加新类型成本递增
6 AST Visitor 缺失 未修复 加节点需改 4 个 switch
7 LLVM 22 无 mem2reg C API 平台限制 IR 含冗余 alloca/store/load

7. 基础设施变更

组件 v0.5 v0.6 影响
链接器 GCC (外部依赖) clang + lld (优先), fallback gcc 用户需安装 LLVM 或将 ld.lld 打包
进程启动 system() CreateProcess 消除 shell 注入/转义风险
发布 NSIS 安装包 (62MB) / 自包含包 (39MB) 零依赖部署
文档 README + CHANGELOG +语言参考手册 (643 行) + CLAUDE.md 开发者友好

8. 与 PRD 对照

PRD v0.1 设定了"学习编译器全流程"的短期目标。对照 PRD 中的非目标列表:

PRD 非目标 (v0.1 不做) 当前状态
字符串类型 v0.2 实现 str
数组/切片/结构体 v0.4-v0.5 实现 struct/array
模块系统 仍缺失
泛型/trait 仍缺失
模式匹配 v0.5 match (简化)
标准库 仍缺失
垃圾回收 不做 (采用 RAII)

v0.6 已大幅超出 v0.1 PRD 范围。建议更新 PRD 到 v0.6 以反映当前功能边界。


9. 推荐开发路线图

v0.7 (短期, 2-3 天)

  1. 独立 desugar pass — 将 guard/pipe/named_args 去糖从 parser 移到独立 pass,改善错误消息和 parser 复杂度
  2. analyze_expr 拆分 — 按节点类型拆分为 4-6 个辅助函数
  3. 枚举关联数据 (ADT)enum Option { Some(i64), None },打开类型安全编程新范式
  4. 表达式作为值let x = if a { 1 } else { 2 },函数体最后表达式即返回值

v0.8 (中期, 1 周)

  1. 模块系统mod + use + pub,多文件编译
  2. if let / while let — 简化 ADT 匹配
  3. 标准库起步: io, convert, vec

v0.9 (中期, 1-2 周)

  1. 泛型 (单态化)
  2. trait / 接口
  3. AST Visitor 宏驱动

本报告由 Codex 自动生成于 2026-06-06 00:50。自上次代码基线 a15cd9d (v0.5) 以来共 20 个提交, +2483/-163 行。P0 扩展 6 个新特性全部实现, 语法完成差异化定型, 链接器/进程启动基础设施升级。v0.7 应聚焦 parser 结构优化和枚举 ADT。