feat: L Language v0.1 编译器完整实现
5 阶段编译流水线: 词法分析 → 语法分析(Pratt) → 语义分析(类型推断) → LLVM IR → .exe 模块: - lexer: 手写状态机, 40 种 Token, // 和 /* */ 注释 - parser: Pratt 表达式解析(9 级优先级) + 递归下降语句/函数 - ast: 14 种节点类型 + 工厂函数 - sema: 作用域链符号表 + 类型推断 + 类型检查 - codegen: AST → LLVM-C API, print_i64/f64/bool 内建 - driver: 命令行 + 流水线串联 + 错误报告 - util: Arena bump allocator (8MB) 测试: 65 单元测试(词法41+语法15+语义9) + 5 集成测试 全部通过 语言特性: i64/f64/bool/void, let不可变变量, if/else, while, 递归函数
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# CLAUDE.md
|
||||
|
||||
## 项目概述
|
||||
|
||||
L Language v0.1 — 用 C17 实现的静态类型编译型编程语言,Rust 风格语法,LLVM 22.x 后端。经典 5 阶段流水线:词法 → 语法 → 语义 → IR → 可执行文件。
|
||||
|
||||
## 构建命令
|
||||
|
||||
```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.1)
|
||||
|
||||
- `let` 变量不可变(无 `mut`),循环计数器无法修改 — 迭代算法需递归实现
|
||||
- 无字符串类型(`print_*` 是编译器内建,非语言特性)
|
||||
- 无数组、结构体、枚举、泛型、trait
|
||||
- 无模块系统(所有函数在单文件)
|
||||
- 作用域未清理(同函数内变量名不可重用)
|
||||
- `main` 返回值未被 OS 使用(需 CRT 包装)
|
||||
|
||||
## 版本号升级清单
|
||||
|
||||
| 文件 | 字段 |
|
||||
|------|------|
|
||||
| `CMakeLists.txt` | `VERSION` 变量 |
|
||||
| `README.md` | badges |
|
||||
| `CHANGELOG.md` | 版本标题 |
|
||||
Reference in New Issue
Block a user