Files
l-language/docs/architecture-review-2026-06-07.md
T

7.8 KiB

L Language 架构与代码审查报告

日期: 2026-06-07 | 全面手动审查 | HEAD: 35e2691

1. 项目概览

指标 数值
版本 v0.6
语言 C17 (-Wall -Wextra -g)
后端 LLVM 22.x C API
链接器 clang+lld (fallback gcc)
平台 Windows 11 + MinGW-w64
总源码行数 5,039 (32 .c + 20 .h)
单元测试 197 断言 (4 文件, 42 测试函数)
集成测试 36 程序
构建警告 0

2. 编译流水线

源码(.l) → Lexer → Parser(+Desugar) → Sema → Codegen → Target → clang+lld → .exe
           72 Token   27 AST 节点         类型标注   LLVM IR    .o 文件   可执行文件

2.1 各阶段文件清单

阶段 文件 行数 职责
include/ l_lang.h 55 TypeKind 枚举 (14), TypeInfo, SourceLoc
lexer/ lexer.c (180) + token.c (60) + .h (55+13) 308 手写状态机, 72 Token 类型
parser/ parser.c (564) + expr.c (484) + desugar.c (109) + parse_internal.h (71) + .h (13+30) 1,271 递归下降+Pratt, 5 种去糖独立化
ast/ ast.c (284) + ast.h (183) + visit.c (17) + visit.h (25) 509 27 AST 节点 + 工厂函数 + Visitor dispatch
sema/ typeck.c (652) + sema.c (500) + symbol.c (172) + type_table.c (36) + .h (57+84+22) 1,535 类型推断+检查, 泛型单态化, 数据驱动类型表
codegen/ codegen.c (453) + cg_expr.c (440) + target.c (35) + .h (83+15+21) 1,047 LLVM IR 生成, 目标输出, 符号表
driver/ main.c (232) + error.c (49) + .h (26) 307 流水线串联, 错误报告
util/ arena.c (45) + arena.h (17) 62 Bump allocator (8MB)

2.2 文件大小分布

所有核心 .c 文件均 ≤ 652 行(限制 800):

typeck.c    652  ████████████████████
parser.c    564  █████████████████
sema.c      500  ████████████████
expr.c      484  ███████████████
codegen.c   453  ██████████████
cg_expr.c   440  ██████████████

3. 类型系统

3.1 Token 类型: 72 种

类别 数量 示例
关键字 20 fn, let, var, if, else, while, for, in, return, guard, struct, type, enum, extend, match, pub, mod, use, trait, Self
类型 8 i32, i64, u64, f64, bool, char, str, void
字面量 6 INT_LIT, FLOAT_LIT, CHAR_LIT, true, false, STR_LIT
标识符 2 IDENT, UNDERSCORE
算术 5 + - * / %
比较 6 == != < > <= >=
逻辑 4 && || |> !
箭头 3 -> to =>
复合赋值 4 += -= *= /=
括号 4 ( ) { }
方括号 2 [ ]
分隔符 4 , : ; =
特殊 4 . :: EOF ERROR

3.2 TypeKind: 14 种

  • 内置: i32, i64, u64, f64, bool, char, str, void
  • 复合: struct, enum, array
  • 内部: GENERIC (泛型参数), UNKNOWN (未推断), ERROR (类型错误)

3.3 TypeTable 数据驱动

type_table.c 统一管理类型元数据(promote_rank, bit_width, is_signed, is_numeric),promote/can_implicit_convert/is_numeric/is_comparable 全部查表。新增类型只需在 TABLE[] 加一行。

4. AST 节点: 27 种

类别 节点
程序结构 PROGRAM, FUNCTION, PARAMETER, BLOCK, MOD_DECL, USE_DECL
语句 LET_STMT, ASSIGN_STMT, IF_STMT, WHILE_STMT, RETURN_STMT, EXPR_STMT, ARRAY_ASSIGN_STMT
表达式 BINARY_EXPR, UNARY_EXPR, CALL_EXPR, LITERAL_EXPR, IDENT_EXPR, FIELD_ACCESS, INDEX_EXPR, METHOD_CALL
类型/声明 STRUCT_DECL, STRUCT_INIT, TYPE_ALIAS, ENUM_DECL, ENUM_VARIANT, IMPL_BLOCK, TRAIT_DECL

新增节点流程:ast.h 加枚举 → ast.c 加工厂 → typeck.c 的 analyze_expr_init() 加一行 handler → 编译器检查未初始化的函数指针。

5. 已实现功能

5.1 P0 基础 (10 项)

基础类型 (i64/f64/bool/void), 控制流 (if/else/while/return), let/var 变量, str 类型+拼接, for..in 去糖, struct 声明+初始化+字段访问

5.2 P1 类型与抽象 (5 项)

type 别名, enum 声明+变体, 固定数组+索引, impl/extend 方法块, match 去糖

5.3 P0 扩展 (5 项)

i32/u64/char, guard 守卫, 命名参数, 管道 |>, 字符串插值

5.4 P2 (6 项) — 全部完成

ADT 枚举关联数据, 表达式作为值 (if-expr), if let, 模块系统 (mod), 泛型单态化, trait 接口

6. 测试覆盖

测试文件 函数 断言 覆盖范围
test_lexer.c 3 41 基础 token, 关键字, 运算符
test_parser.c 20 54 全语法特性
test_sema.c 24 74 类型检查, 错误检测
test_codegen.c 10 28 LLVM IR 生成验证
单元合计 57 197
programs/*.l 36 端到端集成

全部通过,零失败,零构建警告。

7. 近期重构成果

重构 效果
parser.c 1211→564+484+109 表达式/语句/去糖分离
sema.c 1129→500+652 入口/表达式检查分离
codegen.c 947→453+440 语句/表达式生成分离
desugar.c 独立化 match/guard/for/if-let/复合赋值 5 种去糖提取
TypeTable 数据驱动 promote/convert/numeric 查表,新增类型 7→3-4 文件
AST Visitor dispatch analyze_expr switch→vtable,新增节点加一行
error.c arena 化 消除项目唯一 malloc/realloc/strdup
test_parser.c 5→20 函数 15→54 断言,覆盖全语法特性

8. 代码质量

8.1 优点

  • 零编译警告: -Wall -Wextra 干净
  • 全测试通过: 197 单元 + 36 集成
  • 内存管理统一: 全部通过 Arena bump allocator,无散落 malloc/free(除 driver 文件读取)
  • 文件大小受控: 所有核心 .c ≤ 652 行
  • 模块边界清晰: 5 阶段流水线,内部头文件隔离实现细节
  • 新增类型/节点低摩擦: TypeTable 一行注册,Visitor 一行注册
  • 去糖独立化: 5 种语法糖从 parser 内联提取为纯函数,可独立测试
  • LLVM 22 适配: 显式 Context 管理,CreateProcess 替代 system()

8.2 待改进

# 严重度 位置 问题 建议
1 parser/expr.c:195, parser/parser.c:497,520 3 处 sprintf 未使用 snprintf 替换为 snprintf,防止标识符过长溢出
2 parser/parser.c:535 use 语句跳过解析,符号导入未实现 实现 use 语句的符号导入语义
3 main.c:192 strcpy(p, ld_args[i]) 用 memcpy+长度检查替代
4 codegen/cg_expr.c 表达式生成仍用 switch (440 行) 后续可转为 Visitor dispatch
5 sema/typeck.c:652 typeck.c 略超 650 行 泛型单态化可提取为 mono.c
6 信息 全局 固定数组 [64]/[256] 带边界检查 当前均有 if (n>=N) 保护,长期可换动态分配

9. 安全审计

检查项 状态
缓冲区溢出 全部使用 snprintf(sizeof) 或有边界检查
格式化字符串 无用户输入直接作为格式串
空指针解引用 所有 arena_alloc 返回值有 NULL 检查
内存泄漏 Arena bump allocator 统一释放
栈溢出 MAX_PARSE_DEPTH/MAX_CODEGEN_DEPTH 限制递归
LLVM 验证 codegen_module 调用 LLVMVerifyModule

10. 架构评估

评分: 8.5/10

  • 流水线设计清晰,每阶段独立可测试
  • 近期重构显著改善模块化(文件拆分、去糖独立、数据驱动类型表)
  • AST 节点新增流程标准化(枚举→工厂→handler 注册)
  • 测试覆盖充足(197 单元 + 36 集成)
  • 剩余问题均为中低优先级,无阻塞性缺陷
  • 主要不足:codegen 表达式层仍为巨型 switch、use 语句未实现

本报告手动审查生成于 2026-06-07。