# CLAUDE.md ## 项目概述 L Language v0.5 — 用 C17 实现的静态类型编译型编程语言,Rust 风格语法,LLVM 22.x 后端。经典 5 阶段流水线:词法 → 语法 → 语义 → IR → 可执行文件。145 单元测试 + 23 集成程序。 ## 语言设计哲学 L 借鉴 Rust 语法骨架(let/mut/struct/impl/match),但有自己的设计理念: 1. **去糖优先** — 复杂语法在 parser 层去糖为简单原语,零 sema/codegen 改动。已验证: for/match/复合赋值。 2. **博采众长** — 从多语言吸收优秀特性,而非单一模仿 Rust: - **Elixir/F#** → 管道运算符 `|>` - **Go** → defer、多返回值 - **Swift** → guard、字符串插值、命名参数 - **Kotlin** → 扩展函数、when 表达式 - **Python** → 列表推导式、装饰器 - **Zig** → comptime 常量折叠 3. **渐进演进** — 先加语法糖(parser 层),后加强类型(sema/codegen 层) ### 候选特性优先级 | 优先级 | 特性 | 来源 | 实现层 | 预计行数 | 独特性 | |--------|------|------|--------|---------|--------| | **P0** | 管道 `\|>` | Elixir/F# | parser | ~30 | 极高 | | **P0** | guard 语句 | Swift | parser | ~15 | 高 | | **P0** | 字符串插值 | Swift/Python | lexer+parser | ~60 | 高 | | **P0** | 命名参数 | Swift/Kotlin | parser | ~50 | 高 | | P1 | 列表推导式 | Python | parser | ~50 | 高 | | P1 | 装饰器 `@` | Python | parser | ~40 | 高 | | P1 | defer | Go/Zig | parser+codegen | ~60 | 中 | | P1 | 扩展函数 | Kotlin | parser+sema | ~80 | 高 | | P1 | when 表达式 | Kotlin | parser | ~30 | 中 | | P2 | 多返回值 | Go | 全流水线 | ~200 | 中 | | P2 | 空安全 `?.` / `??` | Kotlin | sema+codegen | ~150 | 中 | | P2 | comptime 求值 | Zig | sema+codegen | ~200 | 极高 | | P3 | 隐式接口 | Go | sema+codegen | ~300 | 中 | | P3 | in/out 参数 | Carbon/Cpp2 | sema+codegen | ~150 | 高 | ### P0 特性设计 **管道 `|>`** — 数据流从左到右: ```rust let result = 10 |> double() |> add(5); // 脱糖为: add(double(10), 5) ``` **guard** — 提前返回的语法糖: ```rust guard x >= 0 else { return -1; } // 脱糖为: if !(x >= 0) { return -1; } ``` **字符串插值**: ```rust let msg = "Hello, {name}! Age: {age}"; // 脱糖为: "Hello, " + name + "! Age: " + age ``` **命名参数** — 调用点可选标注: ```rust fn drawRect(width: i64, height: i64) { ... } drawRect(width: 10, height: 20); // 命名 drawRect(10, 20); // 位置 ``` ## 构建命令 ```bash # 配置(仅首次) cd build cmake .. -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH="D:/settings/Language/LLVM" # 编译 mingw32-make -j4 # 编译单个目标 mingw32-make l_lang mingw32-make l_lang_lib ``` ## 架构 ``` 源文件(.l) → 词法分析 → 语法分析 → 语义分析 → IR 生成 → 可执行文件 Token[] AstNode* 带类型AST LLVM Module .exe ``` ``` L Language/ ├── include/ │ └── l_lang.h 公共头文件 (TypeKind 枚举, 向前声明) ├── src/ │ ├── lexer/ │ │ ├── token.h/c Token {kind, start, length, line, col} │ │ └── lexer.h/c 手写状态机,40 种 Token 类型 │ ├── parser/ │ │ └── parser.h/c Pratt 表达式 (9 级优先级) + 递归下降语句 │ ├── ast/ │ │ └── ast.h/c 14 种节点 (PROGRAM..IDENT_EXPR) + 工厂函数 │ ├── sema/ │ │ ├── symbol.h/c 作用域链 (Scope* parent 链表) │ │ └── sema.h/c 类型推断 + 类型检查 + 3 个内建函数注册 │ ├── codegen/ │ │ └── codegen.h/c AST → LLVM-C API → LLVMModuleRef │ ├── driver/ │ │ ├── main.c 入口 + 命令行解析 + 流水线串联 │ │ └── error.h/c ErrorInfo / ErrorList 错误报告 │ └── util/ │ └── arena.h/c Bump allocator (8MB, 8 字节对齐) ├── test/ │ ├── test_utils.h 断言宏 (ASSERT / TEST_RUN / test_summary) │ ├── test_lexer.c 词法测试 (41 tests) │ ├── test_parser.c 语法测试 (15 tests) │ ├── test_sema.c 语义测试 (9 tests) │ └── programs/ .l 集成测试 (5 个程序) ├── docs/ │ ├── PRD.md 产品需求文档 │ └── superpowers/plans/ 实现计划 ├── CMakeLists.txt l_lang_lib (静态库) + l_lang (exe) + 测试 └── README.md ``` ## 核心 API 参考 ### 词法分析 ```c // lexer.h Token* lex(Arena* a, const char* source, const char* filename, size_t* count, ErrorInfo* error); // 返回: Token 数组(分配在 arena),出错返回 NULL // Token: {TokenKind kind, const char* start, int length, int line, int col} ``` ### 语法分析 ```c // parser.h AstNode* parse(Arena* a, const Token* tokens, size_t count, const char* filename, ErrorInfo* error); // 返回: AST_PROGRAM 节点,出错返回 NULL // 支持: 所有语句 (let/if/while/return) + 表达式 (Pratt precedence climbing) ``` ### 语义分析 ```c // sema.h void sema_analyze(AstNode* ast, ErrorList* errors, Arena* arena); // 副作用: AST 节点填充 type 字段, errors 收集类型错误 // 内建: scope_insert_function(print_i64, print_f64, print_bool) ``` ### 代码生成 ```c // codegen.h LLVMModuleRef codegen_module(AstNode* ast, const char* module_name, const char** error_msg); // 返回: 已验证的 LLVM Module,出错返回 NULL // 内建 print_* 函数生成对应的 printf 调用 ``` ## 类型系统 | L 类型 | LLVM 类型 | C 常量创建 | |--------|-----------|-----------| | `i64` | `LLVMInt64Type()` | `LLVMConstInt(ty, val, true)` | | `f64` | `LLVMDoubleType()` | `LLVMConstReal(ty, val)` | | `bool` | `LLVMInt1Type()` | `LLVMConstInt(ty, val, false)` | | `void` | `LLVMVoidType()` | — | 类型推断规则: - 字面量:`42` → `i64`, `3.14` → `f64`, `true` → `bool` - `let x = expr` → 从 expr 推断 - `let x: i64 = expr` → 显式标注优先 - 算术运算:i64 + i64 → i64, i64 + f64 → f64 (提升) - 比较运算:返回 `bool` ## 运算符优先级 | 优先级 | 运算符 | |--------|--------| | 70 (最高) | `-` (一元负), `!` (一元非) | | 60 | `*` `/` `%` | | 50 | `+` `-` | | 40 | `==` `!=` `<` `>` `<=` `>=` | | 30 | `&&` | | 20 | `\|\|` | | 10 (最低) | — | ## 错误处理 | 阶段 | 策略 | |------|------| | 词法分析 | 首个非法字符 → 立即终止,返回 ErrorInfo | | 语法分析 | 首个语法错误 → 立即终止,返回 ErrorInfo | | 语义分析 | 收集所有类型错误到 ErrorList → 批量输出 (ANSI 红色) | | IR 生成 | LLVMVerifyModule → 返回 char* 错误消息 | | 链接 | system() 返回值检查 → 打印 exit code | | 分配失败 | arena_alloc 返回 NULL → 逐层检查 | ## 测试 ```bash # 单元测试 (每个 test_*.c 独立编译运行,各有自己的 main) ./l_lang_lexer_test.exe # 41 个断言 ./l_lang_test.exe # 15 个断言 ./l_lang_sema_test.exe # 9 个断言 # 集成测试 (编译 .l → 运行 .exe → 检查输出) for f in ../test/programs/*.l; do echo "=== $f ===" ./l_lang.exe "$f" -o /tmp/out.exe && /tmp/out.exe done ``` ## 关键约束 - **C17 标准**:`-Wall -Wextra -g`,零编译警告 - **Arena 分配**:Token、AST、符号表全部从 arena 分配,无 malloc/free 散落 - **LLVM 路径**:`D:\settings\Language\LLVM`,C API 头文件手动补充(v22.1.7 预编译包缺少部分头文件) - **链接器**:MinGW 环境用 **gcc** 链接(非 clang,避免 MSVC 依赖) - **Windows**:仅支持 Windows 11 + MinGW-w64 - **错误消息**:中文,格式 `文件名:行号:列号: 描述` ## 已知限制 (v0.5) - 无泛型 (单态化) - 无 trait / 接口 - 无模块系统(所有代码单文件) - 无指针/引用类型 - 借用检查 (远期) - 嵌套数组支持有限 - `match` 仅语句级(非表达式) ## 版本号升级清单 | 文件 | 字段 | |------|------| | `CMakeLists.txt` | `VERSION` 变量 | | `README.md` | badges | | `CHANGELOG.md` | 版本标题 |