270 lines
8.1 KiB
Markdown
270 lines
8.1 KiB
Markdown
<p align="center">
|
||
<h1>L Language</h1>
|
||
<p>用 C17 实现的静态类型编译型编程语言</p>
|
||
</p>
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/version-0.6.0-blue" alt="version">
|
||
<img src="https://img.shields.io/badge/C-17-555555" alt="C">
|
||
<img src="https://img.shields.io/badge/LLVM-22.1.7-4B8BBE" alt="LLVM">
|
||
<img src="https://img.shields.io/badge/GCC-15.x-darkgreen" alt="GCC">
|
||
<img src="https://img.shields.io/badge/tests-158%20passed-brightgreen" alt="tests">
|
||
<img src="https://img.shields.io/badge/license-MIT-green" alt="license">
|
||
</p>
|
||
|
||
---
|
||
|
||
## 简介
|
||
|
||
L Language 是一门学习型编译语言,手写词法分析、递归下降 + Pratt 解析、语义分析和 LLVM IR 代码生成,最终生成原生可执行文件。语法博采众长(Rust/Swift/Elixir),拥有管道、字符串插值、命名参数等独有特性。
|
||
|
||
📖 **[语言参考手册](docs/language-reference.md)** — 完整的语法、类型、示例教程
|
||
|
||
```rust
|
||
fn double(x: i64) -> i64 {
|
||
return x * 2;
|
||
}
|
||
|
||
fn main() -> i64 {
|
||
let name = "L";
|
||
print_str("Hello, \(name)!"); // 字符串插值
|
||
let result = 10 |> double() |> double(); // 管道
|
||
print_i64(result); // 40
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
## 架构
|
||
|
||
```
|
||
源码(.l) → 词法分析(Token) → 语法分析(AST) → 语义分析(类型标注) → LLVM IR → 可执行文件
|
||
```
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph 前端["编译器前端"]
|
||
Lexer[词法分析器<br/>手写状态机<br/>55+ 种 Token]
|
||
Parser[语法分析器<br/>递归下降 + Pratt<br/>25 种 AST 节点]
|
||
Sema[语义分析器<br/>作用域链 + 类型推断<br/>类型检查 + 错误收集]
|
||
end
|
||
|
||
subgraph 后端["编译器后端"]
|
||
Codegen[LLVM IR 生成<br/>AST → LLVM-C API<br/>内建 print 函数]
|
||
Link[链接器<br/>clang/lld<br/>生成 .exe]
|
||
end
|
||
|
||
subgraph 运行时["运行时支持"]
|
||
Builtins[内建函数<br/>print_i64 / print_f64<br/>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*` | 25 种节点 (Program..MethodCall) |
|
||
| `ast/` | — | 工厂函数 | `AstNode` {kind, type, as{union}} |
|
||
| `sema/` | `AstNode*` | 类型标注 | `Scope` 作用域链 + `Symbol` 符号表 |
|
||
| `codegen/` | `AstNode*` | `LLVMModuleRef` | `CgCtx` {module, builder, var_table} |
|
||
| `driver/` | 命令行参数 | exit code | 流水线串联 + 错误报告 |
|
||
|
||
## 功能 (v0.6)
|
||
|
||
### 类型系统
|
||
|
||
| 类型 | 语法 | 示例 |
|
||
|------|------|------|
|
||
| 32 位有符号整数 | `i32` | `100` |
|
||
| 64 位有符号整数 | `i64` | `42`, `-7` |
|
||
| 64 位无符号整数 | `u64` | `999` |
|
||
| 64 位浮点数 | `f64` | `3.14` |
|
||
| 布尔值 | `bool` | `true`, `false` |
|
||
| 字符 | `char` | `'A'` |
|
||
| 字符串 | `str` | `"hello"` |
|
||
| 结构体 | `struct` | `Point { x: i64, y: i64 }` |
|
||
| 枚举 | `enum` | `Color { Red, Green, Blue }` |
|
||
| 数组 | `T[N]` | `i64[10]` |
|
||
| 无返回值 | `void` | 函数默认 |
|
||
| 类型别名 | `type` | `type Meters = i64;` |
|
||
|
||
- `let` 不可变 + `var` 可变,类型推断
|
||
- `i32` → `i64` → `f64` 自动加宽,`char` 可隐式转为整数
|
||
|
||
### 控制流
|
||
|
||
- `if` / `else` / `else if`
|
||
- `while` 循环
|
||
- `for i in 0 to 10` (去糖为 while)
|
||
- `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else)
|
||
- `guard x >= 0 else { return -1; }` (去糖为 if-else)
|
||
- `return`
|
||
|
||
### 函数 & 方法
|
||
|
||
- 多参数、递归、struct 参数/返回值
|
||
- 返回类型校验
|
||
- `extend StructName { fn method(self: Type) -> Ret { ... } }`
|
||
- `instance.method(args)` 调用
|
||
- **命名参数**:`draw_rect(width: 10, height: 20)` 任意顺序传参
|
||
- **管道 `|>`**:`10 |> double() |> add(5)` 数据流从左到右
|
||
- 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str`
|
||
|
||
### 运算符 & 语法糖
|
||
|
||
`+ - * / %` `== != < > <= >=` `&& || !` `+= -= *= /=` `|>` `str + str`
|
||
|
||
- **字符串插值**:`"Hello, \(name)!"` → `"Hello, " + name + "!"`
|
||
|
||
### 内存管理
|
||
|
||
- str 拼接 malloc → 作用域退出自动 free (RAII)
|
||
- struct/array 栈上值类型
|
||
|
||
## 安装
|
||
|
||
### 依赖
|
||
|
||
- **GCC** 15.x (MinGW-w64)
|
||
- **CMake** ≥ 3.20
|
||
- **LLVM** 22.x(C API 库 + 头文件)
|
||
|
||
### 从源码构建
|
||
|
||
```bash
|
||
git clone <repo-url>
|
||
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
|
||
|
||
# 运行全部测试 (158 单元 + 29 集成)
|
||
./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) — 河南理工大学人工智能协会
|