L Language

用 C17 实现的静态类型编译型编程语言

version C LLVM GCC tests license

--- ## 简介 L Language 是一门学习型编译语言,手写词法分析、递归下降 + Pratt 解析、语义分析和 LLVM IR 代码生成,最终生成原生可执行文件。语法借鉴 Rust,类型系统支持类型推断。 📖 **[语言参考手册](docs/language-reference.md)** — 完整的语法、类型、示例教程 ```rust fn fib(n: i64) -> i64 { if n < 2 { return n; } return fib(n - 1) + fib(n - 2); } fn main() -> i64 { print_i64(fib(10)); // 输出 55 return 0; } ``` ## 架构 ``` 源码(.l) → 词法分析(Token) → 语法分析(AST) → 语义分析(类型标注) → LLVM IR → 可执行文件 ``` ```mermaid graph TB subgraph 前端["编译器前端"] Lexer[词法分析器
手写状态机
40 种 Token] Parser[语法分析器
递归下降 + Pratt
14 种 AST 节点] Sema[语义分析器
作用域链 + 类型推断
类型检查 + 错误收集] end subgraph 后端["编译器后端"] Codegen[LLVM IR 生成
AST → LLVM-C API
内建 print 函数] Link[链接器
clang/lld
生成 .exe] end subgraph 运行时["运行时支持"] Builtins[内建函数
print_i64 / print_f64
print_bool → printf] end Source[源码 .l] --> Lexer Lexer --> Parser Parser --> Sema Sema --> Codegen Codegen --> Link Link --> Exe[可执行文件 .exe] Builtins -.-> Codegen ``` ### 模块职责 | 模块 | 输入 | 输出 | 核心结构 | |------|------|------|----------| | `lexer/` | `char*` 源码 | `Token[]` | `Token` {kind, start, length, line, col} | | `parser/` | `Token[]` | `AstNode*` | 14 种节点 (Program..IdentExpr) | | `ast/` | — | 工厂函数 | `AstNode` {kind, type, as{union}} | | `sema/` | `AstNode*` | 类型标注 | `Scope` 作用域链 + `Symbol` 符号表 | | `codegen/` | `AstNode*` | `LLVMModuleRef` | `CgCtx` {module, builder, var_table} | | `driver/` | 命令行参数 | exit code | 流水线串联 + 错误报告 | ## 功能 (v0.5) ### 类型系统 | 类型 | 语法 | 示例 | |------|------|------| | 64 位有符号整数 | `i64` | `42`, `-7` | | 64 位浮点数 | `f64` | `3.14` | | 布尔值 | `bool` | `true`, `false` | | 字符串 | `str` | `"hello"` | | 结构体 | `struct` | `Point { x: i64, y: i64 }` | | 枚举 | `enum` | `Color { Red, Green, Blue }` | | 数组 | `[T; N]` | `[i64; 10]` | | 无返回值 | `void` | 函数默认 | | 类型别名 | `type` | `type Meters = i64;` | - `let` 不可变 + `let mut` 可变,类型推断 - `i64` → `f64` 自动提升 ### 控制流 - `if` / `else` / `else if` - `while` 循环 - `for i in 0..10` (去糖为 while) - `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else) - `return` ### 函数 & 方法 - 多参数、递归、struct 参数/返回值 - 返回类型校验 - `impl StructName { fn method(self: Type) -> Ret { ... } }` - `instance.method(args)` 调用 - 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str` ### 运算符 `+ - * / %` `== != < > <= >=` `&& || !` `+= -= *= /=` `str + str` ### 内存管理 - str 拼接 malloc → 作用域退出自动 free (RAII) - struct/array 栈上值类型 ## 安装 ### 依赖 - **GCC** 15.x (MinGW-w64) - **CMake** ≥ 3.20 - **LLVM** 22.x(C API 库 + 头文件) ### 从源码构建 ```bash git clone cd "L Language" mkdir build && cd build cmake .. -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH="D:/settings/Language/LLVM" mingw32-make -j4 ``` 生成 `l_lang.exe`。 ## 使用 ```bash # 编译并运行 ./l_lang.exe example.l -o example.exe ./example.exe # 查看生成的 LLVM IR ./l_lang.exe example.l --emit-ir ``` ## 开发 ```bash # 构建 cd build && mingw32-make -j4 # 运行全部测试 (145 单元 + 23 集成) ./l_lang_lexer_test.exe # 词法分析 (41 tests) ./l_lang_test.exe # 语法分析 (15 tests) ./l_lang_sema_test.exe # 语义分析 (74 tests) ./l_lang_codegen_test.exe # 代码生成 (28 tests) # 集成测试 for f in ../test/programs/*.l; do ./l_lang.exe "$f" -o out.exe && ./out.exe done ``` ### 技术栈 | 层 | 技术 | |----|------| | 实现语言 | C17 (GCC 15.x) | | 构建系统 | CMake 3.20+ | | IR 后端 | LLVM 22.1.7 C API | | 链接器 | clang / lld | | 内存管理 | Arena bump allocator | | 测试框架 | 手写断言宏 (ASSERT / TEST_RUN / test_summary) | ### 项目结构 ``` include/l_lang.h # 公共类型定义 (TypeKind, 向前声明) src/ ├── lexer/ # 词法分析器 │ ├── token.h/c # Token 类型 + 工具函数 │ └── lexer.h/c # 状态机 lex() ├── parser/ │ └── parser.h/c # Pratt 表达式 + 递归下降 parse() ├── ast/ │ └── ast.h/c # 14 种节点定义 + 创建函数 ├── sema/ │ ├── symbol.h/c # 作用域链 (查/插) │ └── sema.h/c # 类型推断 + 检查 sema_analyze() ├── codegen/ │ └── codegen.h/c # AST → LLVM IR codegen_module() ├── driver/ │ ├── main.c # 入口 + 命令行 + 流水线串联 │ └── error.h/c # 错误报告 (ErrorInfo / ErrorList) └── util/ └── arena.h/c # Bump allocator (8MB) test/ ├── test_utils.h # 断言宏 ├── test_lexer.c # 词法测试 (41 tests) ├── test_parser.c # 语法测试 (15 tests) ├── test_sema.c # 语义测试 (9 tests) └── programs/ # 集成测试 (.l 源文件) docs/ ├── PRD.md # 产品需求文档 └── superpowers/plans/ # 实现计划 ``` ## 错误处理 | 阶段 | 策略 | |------|------| | 词法分析 | 首个非法字符即终止,报告 文件名:行:列: 错误信息 | | 语法分析 | 首个语法错误即终止,报告期望 vs 实际 | | 语义分析 | 收集所有类型错误后批量输出,红色 ANSI 高亮 | | IR 生成 | LLVMVerifyModule 验证失败 → 输出 LLVM 诊断 | | 链接 | system() 返回值检查,失败时打印 exit code | ## 贡献 欢迎提交 Issue 和 Pull Request。 ### 本地开发环境 - GCC 14.x+ (MinGW-w64) - CMake 3.20+ - LLVM 22.x(需要 C API 库和头文件) ### 代码规范 - C17 标准,`-Wall -Wextra -g` 零警告 - 注释用中文 - Arena 内存池贯穿全流水线,不在局部函数内 malloc - 错误信息格式:`文件名:行:列: 描述` - 提交格式:`<类型>: <描述>`(feat/fix/refactor/docs/test/chore) ## 版本号升级清单 版本号需在 **3 个地方** 手动修改: | 文件 | 字段 | 说明 | |------|------|------| | `CMakeLists.txt` | `VERSION` 变量 | CMake `project()` | | `README.md` | badges | 文档徽章 | | `CHANGELOG.md` | 版本标题 | 变更日志 | ## 许可证 MIT License ## 作者 [刘航宇](https://github.com/LHY0125) — 河南理工大学人工智能协会