11 KiB
11 KiB
L Language 语言参考手册
版本 v0.6 | 158 单元 + 29 集成测试全部通过 | LLVM 后端编译型语言
目录
1. 快速开始
Hello, World
fn main() -> i64 {
print_i64(42);
return 0;
}
编译运行:
l_lang.exe hello.l -o hello.exe
./hello.exe
# 输出: 42
程序结构
- 文件扩展名
.l - 一个
.l文件包含若干函数和类型声明 - 必须有
main函数作为入口点 - 所有声明在顶层,不支持嵌套函数
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 |
无返回值 | 用于函数返回类型 |
类型转换
i64和f64混合运算时,i64自动提升为f64bool和数值之间不能隐式转换str不能隐式转换为其他类型
3. 变量
声明
let x = 42; // 不可变,类型推断为 i64
let y: i64 = 100; // 不可变,显式类型标注
let z = 3.14; // 类型推断为 f64
let msg = "hello"; // 类型推断为 str
let flag = true; // 类型推断为 bool
可变变量
var count: i64 = 0; // 可变变量
count = count + 1; // 赋值
count += 1; // 复合赋值 (等价于 count = count + 1)
规则: 对
let声明的不可变变量赋值会在编译时报错。可变变量用var声明。
类型标注语法
let name: Type = value; // 完整写法(不可变)
let name = value; // 类型推断(不可变)
var name: Type = value; // 可变变量
4. 运算符
算术
| 运算符 | 说明 | 示例 |
|---|---|---|
+ |
加法 | 1 + 2 → 3 |
- |
减法 | 5 - 3 → 2 |
* |
乘法 | 3 * 4 → 12 |
/ |
除法 | 10 / 3 → 3 (整数) |
% |
取模 | 10 % 3 → 1 |
比较(返回 bool)
| 运算符 | 说明 |
|---|---|
== |
等于 |
!= |
不等于 |
< |
小于 |
> |
大于 |
<= |
小于等于 |
>= |
大于等于 |
逻辑
| 运算符 | 说明 |
|---|---|
&& |
逻辑与 |
|| |
逻辑或 |
! |
逻辑非 |
复合赋值
| 运算符 | 等价于 |
|---|---|
x += y |
x = x + y |
x -= y |
x = x - y |
x *= y |
x = x * y |
x /= y |
x = x / y |
字符串拼接
let greeting = "Hello, " + "World!";
// greeting = "Hello, World!"
优先级(从高到低)
! -(一元负)
* / %
+ -
== != < > <= >=
&&
||
5. 控制流
if / else
if x > 0 {
print_i64(1);
} else if x == 0 {
print_i64(0);
} else {
print_i64(-1);
}
while 循环
var i: i64 = 0;
while i < 5 {
print_i64(i);
i += 1;
}
// 输出: 0 1 2 3 4
for 循环
for i in 0 to 5 {
print_i64(i);
}
// 输出: 0 1 2 3 4
for i in start to end 等价于 var i = start; while i < end { ...; i += 1; }
match
enum Color { Red, Green, Blue }
let c = Color::Green;
match c {
Color::Red => { print_i64(10); }
Color::Green => { print_i64(20); }
_ => { print_i64(0); } // 通配符
}
// 输出: 20
- 每个分支用
=>分隔,花括号包围 _表示通配符(匹配所有未列出的情况)match是语句,不是表达式
6. 函数
定义
fn add(a: i64, b: i64) -> i64 {
return a + b;
}
fn greet() -> void {
print_str("Hello");
}
fn关键字定义函数- 参数格式:
name: Type - 返回类型:
-> Type,可省略(默认void) - 支持递归调用
调用
let result = add(3, 5);
greet();
命名参数
调用函数时可以标注参数名,命名参数可任意顺序,但必须放在位置参数之后:
fn draw_rect(x: i64, y: i64, w: i64, h: i64) -> void {
// ...
}
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); // 命名任意顺序
用 : 分隔参数名和值(与类型标注 name: Type 视觉统一)。
guard 语句
guard 是提前返回的语法糖,用于提前处理异常条件:
fn abs(x: i64) -> i64 {
guard x >= 0 else { return -x; }
return x;
}
// guard x >= 0 else { ... } 去糖为:
// if !(x >= 0) { ... }
else块必须用花括号,通常包含return/continue等跳转- guard 让正常路径的代码保持在左侧,提高可读性
管道 |>
管道将数据从左到右流经函数,LHS 作为 RHS 函数调用的第一个参数(F#/Elixir 风格):
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
- 管道右侧必须是函数调用(带括号)
- 管道优先级低于所有算术运算符
字符串插值
用 \(expr) 在字符串中嵌入表达式(Swift 风格,\ 与 C 转义字符视觉一致):
let name = "World";
let msg = "Hello, \(name)!";
print_str(msg); // Hello, World!
- 去糖为字符串拼接:
"Hello, " + name + "!" - 字面量
\(写作\\(,反斜杠写作\\
7. 结构体
声明
struct Point {
x: i64,
y: i64,
}
初始化
let p = Point { x: 10, y: 20 };
字段访问
print_i64(p.x); // 10
print_i64(p.y); // 20
嵌套结构体
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 (链式访问)
函数参数和返回值
fn make_point(x: i64, y: i64) -> Point {
return Point { x: x, y: y };
}
fn print_point(p: Point) -> void {
print_i64(p.x);
print_i64(p.y);
}
extend — 方法
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
extend StructName { fn ... }为结构体扩展方法- 第一个参数必须是
self: StructName - 调用:
instance.method(args)
8. 枚举
声明
enum Color {
Red,
Green,
Blue,
}
访问变体
let c = Color::Green;
print_i64(c); // 1 (索引值: Red=0, Green=1, Blue=2)
let is_red = (c == Color::Red); // false
9. 数组
声明类型
let arr: i64[5] = arr; // 声明未初始化的 5 个 i64 数组
数组类型语法: 元素类型[大小](后置维度)
= arr是固定写法,表示声明未初始化的数组(arr是变量名自身)- 大小必须是整数常量
- 元素类型支持:
i64,f64,bool - 数组元素默认值为零值(
0/0.0/false)
索引
arr[0] = 100; // 给第一个元素赋值
arr[1] = 200;
print_i64(arr[0]); // 100
print_i64(arr[1]); // 200
循环遍历
var arr: i64[5] = arr;
var i: i64 = 0;
while i < 5 {
arr[i] = i * 10;
i += 1;
}
10. 类型别名
type Meters = i64;
type Kilometers = i64;
fn run(distance: Meters) -> void {
print_i64(distance);
}
let d: Meters = 5000;
run(d); // 输出: 5000
支持别名指向 struct:
type P = Point;
let p: P = Point { x: 1, y: 2 };
11. 内置函数
| 函数 | 参数 | 输出 |
|---|---|---|
print_i64(x) |
i64 |
整数 + 换行 |
print_f64(x) |
f64 |
浮点 + 换行 |
print_bool(x) |
bool |
true/false + 换行 |
print_str(s) |
str |
字符串 + 换行 |
12. 注释
// 这是单行注释
/*
这是
多行注释
*/
13. 完整示例
斐波那契
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;
}
学生成绩统计
struct Student {
name_id: i64,
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;
}
}
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; }
}
}
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;
}
数组操作
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;
}
return 0;
}
// 输出: 0 1 4 9 16
14. 编译与运行
安装编译器
# 从源码构建
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_lang.exe source.l -o program.exe
# 运行
./program.exe
# 查看生成的 LLVM IR
l_lang.exe source.l --emit-ir
错误信息格式
错误: 文件名:行号:列号: 错误描述
- 词法/语法错误: 立即终止
- 类型错误: 收集所有错误后统一输出
快速参考卡片
类型: 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)!"
注释: // 行注释 /* 块注释 */