diff --git a/docs/language-reference.md b/docs/language-reference.md index fc8832b..67cb36e 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -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 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(x: T) -> T { + return x; +} + +fn swap(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(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(...)` +- 最多 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(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*