Yan

磨墨成言,编译成器

Yan 是一门编译型、静态强类型的小型通用语言。 语法骨架接近 Rust,借用检查也走 Rust 那一路(精简版:不做路径敏感分析)——没有 GC; 默认直接生成原生 exe,也能把 C 打出来交给任意 C 编译器。

v0.11.0 · Windows x64 · 单文件,无运行时依赖

借用检查,生命周期基本不用写

默认按值传递,要引用就显式写 & / &mut; 同一时刻只能有一个 &mut,借用到引用的最后一次使用就结束(NLL),冲突在编译期拦下。 'a 只在两种场合要写:struct 存引用、返回引用的来源不唯一。 不做路径敏感分析——分支和循环里按「借用还活着」保守处理,会比 Rust 报得多。

一个 comptime 管全部编译期求值

常量、comptime f(..)、comptime if 同族;函数定义处零标记—— 同一个函数既能编译期用也能运行期用,不用写两份。

条件编译不是预处理

comptime if 就是常规语法,未选中分支不生成代码(语句位置连检查都跳过); 表达式位置两支照样过类型检查,死分支不会腐烂。

默认直出 exe,也能出 C

原生后端直接产出 Windows x64 的 PE;要落到别的平台,同一份语义生成一个 C 文件,交给那边的 C 编译器。 编译器本体已经用自己编自己,逐字节不动点。

按位访问是语言的一部分

取一位、取一段位,读写皆可。读出来一律无符号(零扩展),写回去只改指定位—— 寄存器字段读写不用再自己算掩码。

位段两端得是编译期常量;取单一位可以用变量下标。

fn main() {
    // 寄存器布局:mode[15:13] | gain[12:8] | offset[7:0]
    let mut reg: u16 = 0xB1C8;

    println("{}", reg[15:13]);  // 5      ← 一次拿一个字段
    reg[12:8] = 3;              // 只改这 5 位
    println("{}", reg);         // 41928(0xA3C8),其余位没动
}

三十秒上手

仓库里带着编译好的编译器,解压就能用,不需要安装任何东西。

编译器不会自己建 build\ 目录,产物也不放在源文件旁边——落在当前目录的 build\ 下,所以请在仓库根目录运行。公开仓带了一个空占位 build\.gitkeep。

:: 编译并运行
bin\yan.exe run examples\hello.yan

:: 产出 build\fib.exe
bin\yan.exe build examples\fib.yan

:: 只做前端检查
bin\yan.exe check examples\arith.yan
fn fib(n: i32) -> i32 {
    if (n < 2) { n } else { fib(n - 1) + fib(n - 2) }
}

fn main() {
    let nums = [4, 8, 15, 16, 23, 42];
    let mut sum = 0;
    for (x in nums) { sum += x; }
    println("fib(20) = {}, sum = {}", fib(20), sum);
}

现在到哪了