docs: language-reference.md v0.7 全面重写

新增章节: 泛型、Trait、模块系统(mod+use+pub)、ADT枚举、if let、if-expr
更新: 类型表(14种)、测试数据(197+37)、版本号、快速参考卡片
This commit is contained in:
2026-06-07 13:38:47 +08:00
parent 1aafde0fd9
commit e60021b684
+346 -341
View File
@@ -1,8 +1,6 @@
# L Language 语言参考手册
> 版本 v0.6 | 158 单元 + 29 集成测试全部通过 | LLVM 后端编译型语言
---
> 版本 v0.7 | 197 单元 + 37 集成测试全部通过 | LLVM 22.x 编译型语言
## 目录
@@ -13,13 +11,16 @@
5. [控制流](#5-控制流)
6. [函数](#6-函数)
7. [结构体](#7-结构体)
8. [枚举](#8-枚举)
8. [枚举与 ADT](#8-枚举与-adt)
9. [数组](#9-数组)
10. [类型别名](#10-类型别名)
11. [内置函数](#11-内置函数)
12. [注释](#12-注释)
13. [完整示例](#13-完整示例)
14. [编译与运行](#14-编译与运行)
11. [泛型](#11-泛型)
12. [Trait 接口](#12-trait-接口)
13. [模块系统](#13-模块系统)
14. [内置函数](#14-内置函数)
15. [注释](#15-注释)
16. [完整示例](#16-完整示例)
17. [编译与运行](#17-编译与运行)
---
@@ -28,77 +29,85 @@
### Hello, World
```rust
fn main() -> i64 {
print_i64(42);
return 0;
fn main() {
print_str("Hello, World!");
}
```
编译运行:
```bash
l_lang.exe hello.l -o hello.exe
./hello.exe
# 输出: 42
l_lang hello.l -o hello.exe && ./hello.exe
```
### 程序结构
- 文件扩展名 `.l`
- 一个 `.l` 文件包含若干函数和类型声明
- 必须有 `main` 函数作为入口点
- 所有声明在顶层,不支持嵌套函数
```rust
type Age = i64; // 类型别名
struct Point { x: i64, y: i64 } // 结构体
enum Color { Red, Green, Blue } // 枚举
fn main() -> i64 {
let p = Point { x: 10, y: 20 };
print_i64(p.x);
return 0;
}
```
---
## 2. 基本类型
| 类型 | 关键字 | 范围/说明 | 示例 |
|------|--------|----------|------|
| 32位整数 | `i32` | 32位有符号,`-2^31 ~ 2^31-1` | `100` |
| 64位整数 | `i64` | 64位有符号,`-2^63 ~ 2^63-1` | `42`, `-7`, `0` |
| 无符号整数 | `u64` | 64位无符号,`0 ~ 2^64-1` | `999` |
| 浮点 | `f64` | 64位双精度 | `3.14`, `-0.5`, `1.0` |
| 布尔 | `bool` | `true``false` | `true`, `false` |
| 字符 | `char` | 字符ASCII | `'A'`, `'\n'` |
| 字符串 | `str` | UTF-8 文本 | `"Hello"`, `"你好"` |
| 空类型 | `void` | 无返回值 | 用于函数返回类型 |
| 类型 | 说明 | 字面量示例 |
|------|------|-----------|
| `i32` | 有符号 32 位 | `let a: i32 = 100;` |
| `i64` | 有符号 64 位(默认整数) | `let a = 42;` |
| `u64` | 无符号 64 位 | `let a: u64 = 999;` |
| `f64` | 双精度浮点 | `let a = 3.14;` |
| `bool` | 布尔 | `let a = true;` |
| `char` | 字符 | `let a = 'A';` |
| `str` | 字符串 | `let a = "hello";` |
| `void` | 无返回值 | 函数返回类型 |
复合类型:`struct`(结构体)、`enum`(枚举/tagged union)、`T[N]`(固定数组)
### 类型转换
- `i64``f64` 混合运算时,`i64` 自动提升为 `f64`
- `bool` 和数值之间**不能**隐式转换
- `str` 不能隐式转换为其他类型
算术运算自动提升(TypeTable 查表驱动):
- `char` `i32`(字符参与算术时提升)
- `enum``i64`(枚举在算术中视为 i64
- 加宽链:`i32``i64``f64`
- `u64``i64` 双向(同 64-bit 位宽,LLVM 同为 i64
---
## 3. 变量
### 声明
### 不可变变量
```rust
let x = 42; // 不可变,类型推断为 i64
let y: i64 = 100; // 不可变,显式类型标注
let z = 3.14; // 类型推断为 f64
let msg = "hello"; // 类型推断为 str
let flag = true; // 类型推断为 bool
let x = 42; // 类型推断为 i64
let y: i64 = 42; // 显式类型标注
```
### 可变变量
```rust
var count: i64 = 0; // 可变变量
count = count + 1; // 赋值
count += 1; // 复合赋值 (等价于 count = count + 1)
var x = 0; // var 声明可变变量
x = 42; // 允许重新赋值
x += 1; // 复合赋值
```
> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。可变变量用 `var` 声明
`let` 声明的变量不可重新赋值(编译错误)
### 类型标注语法
```rust
let name: Type = value; // 完整写法(不可变)
let name = value; // 类型推断(不可变)
var name: Type = value; // 可变变量
let a: i64; // 基本类型
let b: str; // 字符串
let c: f64; // 浮点
let d: Point; // 结构体类型
let e: i64[10]; // 数组类型(后置语法 T[N]
```
---
@@ -107,59 +116,41 @@ var name: Type = value; // 可变变量
### 算术
| 运算符 | 说明 | 示例 |
|--------|------|------|
| `+` | 加法 | `1 + 2``3` |
| `-` | 减法 | `5 - 3``2` |
| `*` | 乘法 | `3 * 4``12` |
| `/` | 除法 | `10 / 3``3` (整数) |
| `%` | 取模 | `10 % 3``1` |
`+` `-` `*` `/` `%`
`+` 用于字符串拼接时调用 `malloc`+`memcpy`,自动 `free`
### 比较(返回 bool
| 运算符 | 说明 |
|--------|------|
| `==` | 等于 |
| `!=` | 不等于 |
| `<` | 小于 |
| `>` | 大于 |
| `<=` | 小于等于 |
| `>=` | 大于等于 |
`==` `!=` `<` `>` `<=` `>=`
### 逻辑
| 运算符 | 说明 |
|--------|------|
| `&&` | 逻辑与 |
| `\|\|` | 逻辑或 |
| `!` | 逻辑非 |
`&&` `||` `!`
### 复合赋值
| 运算符 | 等价于 |
|--------|--------|
| `x += y` | `x = x + y` |
| `x -= y` | `x = x - y` |
| `x *= y` | `x = x * y` |
| `x /= y` | `x = x / y` |
### 字符串拼接
```rust
let greeting = "Hello, " + "World!";
// greeting = "Hello, World!"
var x = 10;
x += 1; // x = x + 1
x -= 1; // x = x - 1
x *= 2; // x = x * 2
x /= 2; // x = x / 2
```
> 去糖为 `x = x <op> expr`
### 优先级(从高到低)
```
! -(一元负)
* / %
+ -
== != < > <= >=
&&
||
```
| 优先级 | 运算符 |
|--------|--------|
| 70 (最高) | `-` (一元负), `!` |
| 60 | `*` `/` `%` |
| 50 | `+` `-` |
| 40 | `==` `!=` `<` `>` `<=` `>=` |
| 30 | `&&` |
| 20 | `||` |
| 10 | `\|>` (管道) |
---
@@ -169,53 +160,76 @@ let greeting = "Hello, " + "World!";
```rust
if x > 0 {
print_i64(1);
} else if x == 0 {
print_i64(0);
print_str("正数");
} else if x < 0 {
print_str("负数");
} else {
print_i64(-1);
print_str("");
}
```
**if 作为表达式**if-expr):
```rust
let a = if x > 0 { 10; } else { 20; };
// a = 10 或 a = 20
```
块的最后一条表达式语句的值即为块的值。
### while 循环
```rust
var i: i64 = 0;
var i = 0;
while i < 5 {
print_i64(i);
i += 1;
i = i + 1;
}
// 输出: 0 1 2 3 4
```
### for 循环
```rust
for i in 0 to 5 {
print_i64(i);
print_i64(i); // 0, 1, 2, 3, 4
}
// 输出: 0 1 2 3 4
```
`for i in start to end` 等价于 `var i = start; while i < end { ...; i += 1; }`
> 去糖为 `var i = 0; while i < 5 { ... ; i = i + 1; }`
### match
```rust
enum Color { Red, Green, Blue }
let c = Color::Green;
match c {
Color::Red => { print_i64(10); }
Color::Green => { print_i64(20); }
_ => { print_i64(0); } // 通配符
match x {
1 => { print_str("one"); },
2 => { print_str("two"); },
_ => { print_str("other"); },
}
// 输出: 20
```
- 每个分支用 `=>` 分隔,花括号包围
- `_` 表示通配符(匹配所有未列出的情况)
- `match` 是语句,不是表达式
> 去糖为 `let __match_val = x; if __match_val == 1 { ... } else if ...`
### guard
```rust
guard x >= 0 else { return -1; }
// 去糖: if !(x >= 0) { return -1; }
```
提前返回的语法糖,让正常路径保持左对齐。
### if let
```rust
enum Option { Some(i64), None }
let val = Option::Some(42);
if let Option::Some(v) = val {
print_i64(v); // 42
} else {
print_str("none");
}
```
---
@@ -228,83 +242,62 @@ fn add(a: i64, b: i64) -> i64 {
return a + b;
}
fn greet() -> void {
print_str("Hello");
fn greet() {
print_str("Hello!");
}
```
- `fn` 关键字定义函数
- 参数格式: `name: Type`
- 返回类型: `-> Type`,可省略(默认 `void`
- 支持递归调用
### 泛型定义
```rust
fn id<T>(x: T) -> T {
return x;
}
fn swap<A, B>(a: A, b: B) -> B {
return b;
}
```
> 单态化:每次泛型调用生成一份具象化副本。最多 8 个类型参数。
### 调用
```rust
let result = add(3, 5);
let result = add(1, 2);
let x = id(42); // T = i64
let y = id("hello"); // T = str
greet();
```
### 命名参数
调用函数时可以标注参数名,命名参数可任意顺序,但必须放在位置参数之后:
```rust
fn draw_rect(x: i64, y: i64, w: i64, h: i64) -> void {
// ...
}
fn draw_rect(width: i64, height: i64) { ... }
draw_rect(0, 0, 100, 200); // 全位置
draw_rect(x: 1, y: 2, w: 10, h: 20); // 全命名
draw_rect(0, 0, w: 10, h: 20); // 混用
draw_rect(w: 10, h: 20, x: 1, y: 2); // 命名任意顺序
draw_rect(width: 10, height: 20); // 命名调用
draw_rect(10, 20); // 位置调用(等价)
```
`:` 分隔参数名和值(与类型标注 `name: Type` 视觉统一)
命名参数必须在位置参数之后
### guard 语句
guard 是提前返回的语法糖,用于提前处理异常条件:
### 管道
```rust
fn abs(x: i64) -> i64 {
guard x >= 0 else { return -x; }
return x;
}
// guard x >= 0 else { ... } 去糖为:
// if !(x >= 0) { ... }
let result = 10 |> add(5); // add(10, 5)
let x = 1 |> add(2) |> mul(3); // mul(add(1, 2), 3)
```
- `else` 块必须用花括号,通常包含 `return`/`continue` 等跳转
- guard 让正常路径的代码保持在左侧,提高可读性
### 管道 `|>`
管道将数据从左到右流经函数,LHS 作为 RHS 函数调用的第一个参数(F#/Elixir 风格):
```rust
fn double(x: i64) -> i64 { return x * 2; }
fn add(a: i64, b: i64) -> i64 { return a + b; }
let result = 10 |> double() |> add(5);
// 去糖为: add(double(10), 5) → 25
```
- 管道右侧必须是函数调用(带括号)
- 管道优先级低于所有算术运算符
> 去糖为嵌套调用,RHS 必须是函数调用形式(带括号)。
### 字符串插值
`\(expr)` 在字符串中嵌入表达式(Swift 风格,`\` 与 C 转义字符视觉一致):
```rust
let name = "World";
let msg = "Hello, \(name)!";
print_str(msg); // Hello, World!
let msg = "Hello, \(name)!"; // "Hello, World!"
```
- 去糖为字符串拼接: `"Hello, " + name + "!"`
- 字面量 `\(` 写作 `\\(`,反斜杠写作 `\\`
> 去糖为 `"Hello, " + name + "!"`
---
@@ -313,137 +306,95 @@ print_str(msg); // Hello, World!
### 声明
```rust
struct Point {
x: i64,
y: i64,
}
struct Point { x: i64, y: i64 }
```
### 初始化
```rust
let p = Point { x: 10, y: 20 };
let q = Point { y: 30, x: 5 }; // 命名顺序任意
```
### 字段访问
```rust
print_i64(p.x); // 10
print_i64(p.y); // 20
```
### 嵌套结构体
```rust
struct Rect {
tl: Point, // 左上角
br: Point, // 右下角
}
let r = Rect {
tl: Point { x: 0, y: 10 },
br: Point { x: 5, y: 0 },
};
print_i64(r.tl.x); // 0 (链式访问)
let px = p.x;
```
### 函数参数和返回值
```rust
fn make_point(x: i64, y: i64) -> Point {
return Point { x: x, y: y };
}
fn distance(p1: Point, p2: Point) -> f64 { ... }
fn print_point(p: Point) -> void {
print_i64(p.x);
print_i64(p.y);
fn create_point(x: i64, y: i64) -> Point {
return Point { x: x, y: y };
}
```
### extend — 方法
### 方法(extend
```rust
extend Point {
fn new(x: i64, y: i64) -> Point {
return Point { x: x, y: y };
}
fn get_x(self: Point) -> i64 {
return self.x;
}
}
let p = Point.new(10, 20); // 方法调用
print_i64(p.get_x()); // 10
let p = Point { x: 10, y: 20 };
p.get_x(); // 10
```
- `extend StructName { fn ... }` 为结构体扩展方法
- 第一个参数必须是 `self: StructName`
- 调用: `instance.method(args)`
> 方法名内部 mangled 为 `StructName$methodName`
---
## 8. 枚举
## 8. 枚举与 ADT
### 声明
### 简单枚举
```rust
enum Color {
Red,
Green,
Blue,
enum Color { Red, Green, Blue }
let c = Color::Red;
print_i64(c); // 0 (变体索引)
```
### 带数据的枚举 (ADT)
```rust
enum Option {
Some(i64),
None,
}
let x = Option::Some(100);
```
### 访问变体
内部表示为 `{ tag: i64, payload: i64 }` tagged union。
### match 枚举 + 解构
```rust
let c = Color::Green;
print_i64(c); // 1 (索引值: Red=0, Green=1, Blue=2)
```
```rust
let is_red = (c == Color::Red); // false
match color {
Color::Red => { print_str("red"); },
_ => { print_str("other"); },
}
```
---
## 9. 数组
### 声明类型
```rust
let arr: i64[5] = arr; // 声明未初始化的 5 个 i64 数组
let arr: i64[3] = arr;
var nums: i64[10];
nums[0] = 42;
let x = nums[0];
```
数组类型语法: `元素类型[大小]`(后置维度)
- `= arr` 是固定写法,表示声明未初始化的数组(`arr` 是变量名自身)
- 大小必须是整数常量
- 元素类型支持: `i64`, `f64`, `bool`
- 数组元素默认值为零值(`0` / `0.0` / `false`
### 索引
```rust
arr[0] = 100; // 给第一个元素赋值
arr[1] = 200;
print_i64(arr[0]); // 100
print_i64(arr[1]); // 200
```
### 循环遍历
```rust
var arr: i64[5] = arr;
var i: i64 = 0;
while i < 5 {
arr[i] = i * 10;
i += 1;
}
```
> 后置语法 `T[N]`,大小仅支持整数字面量。元素类型支持 i64/f64/bool/struct。
---
@@ -451,63 +402,163 @@ while i < 5 {
```rust
type Meters = i64;
type Kilometers = i64;
type Point3D = Point;
fn run(distance: Meters) -> void {
print_i64(distance);
let distance: Meters = 100;
```
> 别名在 sema 层完全解析为零 codegen 开销。
---
## 11. 泛型
```rust
fn id<T>(x: T) -> T { return x; }
fn main() -> i64 {
let a = id(42); // T = i64,生成 id_i64
let b = id("hello"); // T = str,生成 id_str
return 0;
}
let d: Meters = 5000;
run(d); // 输出: 5000
```
支持别名指向 struct:
- 函数级类型参数:`fn name<A, B, ...>(...)`
- 最多 8 个类型参数
- 单态化:调用时生成具象化副本,替换 AST 中所有 T 引用
- 类型参数可用在参数和返回值位置
---
## 12. Trait 接口
### 定义
```rust
type P = Point;
let p: P = Point { x: 1, y: 2 };
trait Show {
fn show(self: Self) -> void;
}
```
`Self` 关键字在 trait 签名中代表实现者的类型。
### 实现
```rust
extend Show Point {
fn show(self: Point) -> void {
print_i64(self.x);
print_i64(self.y);
}
}
```
### 调用
```rust
let p = Point { x: 10, y: 20 };
p.show(); // 通过 trait 方法 dispatch
```
> 内部 mangled 为 `Point$Show$show`dot-call 自动搜索 `$show` 后缀。
---
## 13. 模块系统
### 声明子模块
```rust
// main.l
mod math; // 加载同目录下 math_mod.l
fn main() -> i64 {
return math_mod::add(3, 4);
}
```
子模块中 `pub` 标记对外可见:
```rust
// math_mod.l
pub fn add(a: i64, b: i64) -> i64 {
return a + b;
}
```
### use 导入
```rust
use math_mod::add;
fn main() -> i64 {
return add(3, 4); // 零前缀直接调用
}
```
---
## 11. 内置函数
## 14. 内置函数
| 函数 | 参数 | 输出 |
|------|------|------|
| `print_i64(x)` | `i64` | 整数 + 换行 |
| `print_f64(x)` | `f64` | 浮点 + 换行 |
| `print_bool(x)` | `bool` | `true`/`false` + 换行 |
| `print_str(s)` | `str` | 字符串 + 换行 |
| 函数 | 输出格式 |
|------|----------|
| `print_i64(x: i64)` | `%lld\n` |
| `print_f64(x: f64)` | `%f\n` |
| `print_bool(x: bool)` | `true\n` / `false\n` |
| `print_str(x: str)` | `%s\n` |
> 内置函数委托给 C `printf`,无需导入。
---
## 12. 注释
## 15. 注释
```rust
// 这是单行注释
// 单行注释
/*
这是
多行注释
*/
```
不支持嵌套多行注释。
---
## 13. 完整示例
## 16. 完整示例
### 斐波那契
```rust
fn fib(n: i64) -> i64 {
if n < 2 {
return n;
}
if n <= 1 { return n; }
return fib(n - 1) + fib(n - 2);
}
fn main() -> i64 {
print_i64(fib(10)); // 55
return fib(10); // 55
}
```
### Trait + 泛型
```rust
trait Show {
fn show(self: Self) -> void;
}
struct Point { x: i64, y: i64 }
extend Show Point {
fn show(self: Point) -> void {
print_i64(self.x);
print_i64(self.y);
}
}
fn main() -> i64 {
let p = Point { x: 10, y: 20 };
p.show();
return 0;
}
```
@@ -515,16 +566,9 @@ fn main() -> i64 {
### 学生成绩统计
```rust
struct Student {
name_id: i64,
score: i64,
}
struct Student { name: str, score: i64 }
extend Student {
fn new(id: i64, score: i64) -> Student {
return Student { name_id: id, score: score };
}
fn is_pass(self: Student) -> bool {
return self.score >= 60;
}
@@ -533,111 +577,72 @@ extend Student {
enum Grade { A, B, C, D, F }
fn get_grade(score: i64) -> i64 {
match score {
90 => { return 0; }
80 => { return 1; }
70 => { return 2; }
60 => { return 3; }
_ => { return 4; }
}
if score >= 90 { return 0; }
if score >= 80 { return 1; }
if score >= 70 { return 2; }
if score >= 60 { return 3; }
return 4;
}
fn main() -> i64 {
let s = Student.new(1001, 85);
print_i64(s.name_id);
print_i64(s.score);
if s.is_pass() {
print_str("PASS");
} else {
print_str("FAIL");
}
print_i64(get_grade(85)); // 1 (Grade::B)
return 0;
let s = Student { name: "Tom", score: 85 };
if s.is_pass() { print_str("pass"); }
return get_grade(s.score);
}
```
### 数组操作
### 模块化
```rust
// math_mod.l
pub fn add(a: i64, b: i64) -> i64 { return a + b; }
// main.l
use math_mod::add;
fn main() -> i64 {
var arr: i64[5] = arr;
// 填充数组
var i: i64 = 0;
while i < 5 {
arr[i] = i * i;
i += 1;
}
// 打印数组
i = 0;
while i < 5 {
print_i64(arr[i]);
i += 1;
}
print_i64(add(3, 4)); // 7
return 0;
}
// 输出: 0 1 4 9 16
```
---
## 14. 编译与运行
## 17. 编译与运行
### 安装编译器
### 安装
```bash
# 从源码构建
git clone git@lhy-git.liuhangyv.top:Serendipity/l-language.git
cd l-language
mkdir build && cd build
cmake .. -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH="D:/settings/Language/LLVM"
mingw32-make -j4
```
依赖: GCC 15.x (MinGW-w64), CMake 3.20+, LLVM 22.x
下载 `L-Language-0.7.0-setup.exe`39.2MB,自包含 LLVM + MinGW)。
### 使用
```bash
# 编译
l_lang.exe source.l -o program.exe
# 运行
./program.exe
# 查看生成的 LLVM IR
l_lang.exe source.l --emit-ir
l_lang source.l # 编译并自动运行
l_lang source.l -o output.exe # 指定输出路径
```
### 错误信息格式
### 错误格式
```
错误: 文件名:行号:列号: 错误描述
错误: 文件名:行号:列号: 描述
```
- 词法/语法错误: 立即终止
- 类型错误: 收集所有错误后统一输出
---
## 快速参考卡片
## 快速参考
```
类型: i32 i64 u64 f64 bool char str void struct enum T[N]
声明: let x = val var x = val
let x: Type = val type Alias = Type
控制流: if/else while for i in 0 to N match guard
函数: fn name(p: T) -> Ret { return expr; }
func(name: val) 命名参数 expr |> func() 管道
结构体: struct Name { f: Type } Name { f: val }
枚举: enum Name { A, B, C } Name::B
方法: extend T { fn m(self: T) } obj.m()
内建: print_i64 print_f64 print_bool print_str
运算符: + - * / % == != < > <= >= && || ! += -= *= /= |>
插值: "Hello, \(name)!"
注释: // 行注释 /* 块注释 */
变量: let x = 42 var x = 0 let x: i64 = 0
控制流: if/else while for i in 0 to N match guard if let
函数: fn f(a: T) -> R { return expr; } 泛型: fn id<T>(x: T) -> T
结构体: struct S { x: i64 } Point { x: 1 } . extend + method
枚举: enum E { A, B } Option::Some(v) if let Option::Some(v) = x
Traits: trait Show { fn show(self: Self); } extend Trait Struct { ... }
模块: mod math; use math::add; pub fn
管道: expr |> func() 插值: "Hello, \(name)!"
```
---
*v0.7 — 最后更新 2026-06-07*