Leno

Leno 是一门带静态类型检查的脚本语言。由 C 语言实现,编译为字节码在虚拟机上运行。

Leno 诞生于对编程语言设计的热爱与探索,虽非完美,但乐在其中。

一分钟速览

// 类型推断 + 静态检查
var name = "Leno"
const PI = 3.14

// 结构体 + 方法
struct Point {
    int x = 0
    int y = 0
    func dist():float { return maths.sqrt(x * x + y * y) }
}
var p = new Point(x = 3, y = 4)
print(p.dist())    // 5.0

// 接口 + 多态
face Shape {
    func area():float
}
struct Circle impl Shape {
    int r = 0
    func area():float { return 3.14 * r * r }
}

// 多返回值 + 解构
func minMax(Array[int] arr): [int, int] {
    return arr[0], arr[-1]
}
var[int, int](lo, hi) = minMax([3, 1, 9, 7])
print(lo, hi)    // 1, 9

// 泛型 struct(类型参数运行时精准传递)
struct Result[T] {
    T data
    bool ok = false
}
func Ok[T](T val): Result[T] { return new Result[T](data=val, ok=true) }
var r = Ok[int](42)
print(r.data)     // 42

// 泛型约束 [T: Face](编译期检查方法完整性)
face Comparable {
    func compare(Comparable other): int
}
func maxBy[T: Comparable](T a, T b): T {
    if a.compare(b) >= 0 { return a }
    return b
}

// 匿名函数 + 闭包
func make_counter(int start) {
    int count = start
    return func():int { count = count + 1; return count }
}

// 安全访问 + 空值合并
string? maybe_name = get_name()
var display = maybe_name ?? "anonymous"
var len = maybe_name?.len() ?? 0

// 异步协程
async func fetch():string {
    import asyncs
    await asyncs.sleep(100)
    return "done"
}

// 异常处理
try {
    var a = 1 / 0
} catch e {
    print("出错: " + e.msg)
}

特性

类型系统

  • 静态类型 + 类型推断 — 显式声明或 var 自动推断,类型一旦确定不可更改
  • const 常量 — 不可变绑定,声明时必须初始化,支持类型推断和显式类型
  • 任意精度整数 — int 无溢出,int48 内联存储 + BigInt 自动升级,对外完全透明
  • 固定位宽转换 — _int32() / _int64() / _uint32() / _uint64() / _uint8() / _byte() 精确控制位宽
  • alias 类型别名 — 支持简单类型、Array[T]、Dict[K,V]、别名链等复杂组合
  • 类型守卫 — is 类型检查 + if/switch 块内自动类型收窄
  • => 绑定语法 — if expr is Type => var 一次性求值、绑定、类型收窄
  • 索引类型收窄 — arr[0] is int 后续使用自动收窄,支持连续索引 a[0]["k"] is Type
  • and 链 + => 绑定 — 多条件守卫组合,收窄传导到局部变量
  • 安全类型转换 — as 操作符,不匹配返回 null 而非崩溃
  • 可空类型 — Type? 语法,int? / string? / Point? 等

结构体与面向对象

  • struct 结构体 — 字段、方法、嵌套、自引用,堪比轻量级 class
  • 泛型 struct — struct Stack[T]、struct Result[T],类型参数沿调用链精准传递
  • self 关键字 — 方法内显式引用当前实例,self 可选但冲突时必备
  • face 接口 — 名义类型,显式 impl 声明,编译期检查方法完整性,支持 export face
  • 多 face 实现 — struct Key impl Comparable, Hashable { } 同时实现多个接口
  • 泛型约束 — func maxBy[T: Comparable](T a, T b): T,T 必须实现指定 face
  • 泛型 face — face Container[T] { func get(): T } 接口级别泛型
  • 绑定方法引用 — return item.format 返回方法的绑定引用
  • enum 枚举 — 自增值或显式值,本质为 int

函数式编程

  • 一等函数 — 函数赋值给变量、作为参数传递、作为返回值
  • 匿名函数 / Lambda — func(x) { return x * 2 } 内联定义,支持 IIFE
  • 闭包 — 捕获外部变量,状态保持,多实例独立
  • 泛型函数 — func map[T, U](Array[T] arr, func(T):U fn):Array[U]
  • 默认参数 — func add(int x, int y = 10):int
  • 多返回值 — func f(): [int, string] { return 42, "ok" }
  • 前向引用 — 函数可以先调用后定义

解构声明

  • 数组解构 — var[int, int](a, b) = [10, 20] 按索引提取
  • 字典解构 — var{"host": string, "port": int}(host, port) = config 按键名提取
  • 多返回值解构 — var[int, string](id, name) = get_user()
  • 部分解构 — 变量数可少于数据源(多余丢弃),也可多于(补 null)
  • const 解构 — const[int, int](a, b) = data 声明不可变绑定
  • export 解构 — 模块中解构变量可导出供其他模块使用

模块系统

  • import 导入 — 文件模块、内置包、相对路径、中文/空格路径
  • export 控制 — 变量/函数/struct/enum/face/alias 显式导出
  • export alias — 模块导出类型别名,支持复杂类型和别名链
  • use 类型导入 — use module.Struct 导入 struct/face 到当前作用域
  • use 链式传导 — D→C→B→A 自动传递类型,无需每层重导出
  • 循环依赖支持 — A↔B 相互导入,占位符机制防止无限递归
  • 模块缓存 / 单例 — 同模块多次导入共享同一实例,状态全局一致
  • 编译缓存 — .lenocache 磁盘缓存,模块编译结果跨运行复用,含依赖一致性校验
  • 包管理 — leno.toml 配置、leno --init 创建、leno --install 安装

并发编程

  • 多线程 — threads 模块,start()/join()/通道通信,线程间全局变量隔离
  • 异步协程 — async/await + 事件循环,轻量并发
  • Channel 通道 — 有缓冲/无缓冲,Go 风格 CSP 模型

底层能力

  • FFI — 直接调用 C 动态库和系统 API,无需绑定
  • CStruct — 声明式定义 C 结构体布局,packed/align 属性控制对齐
  • & 取地址 — 获取变量地址用于 FFI 输出参数
  • FFI 输出参数 — &var 引用传递,或手动 ffi.write_int 两种写法

异常处理

  • try-catch-finally — 完整异常机制,支持嵌套和 throw 重抛
  • 异常对象 — e.msg/e.file/e.stack 完整诊断信息
  • 线程异常传播 — 子线程异常通过 join() 传播到调用方

运算符

  • 安全访问 ?. — obj?.field、obj?.method() 空安全链式调用
  • 空值合并 ?? — expr ?? default 左侧为 null 时取右侧默认值
  • 成员检查 in / not in — 数组、字典、子串检查
  • 逻辑右移 >>> — 高位补 0,适合加密算法
  • 位复合赋值 — &=, |=, ^=, <<=, >>=, >>>=
  • 复合赋值 — +=, -=, *=, /=, %=
  • 自增自减 — ++, --

其他

  • 泛型容器 — Array[T]、Dict[K, V] 内置泛型数组与字典,支持 map/filter/reduce
  • 数组切片 — arr[2:8]、arr[:5]、arr[3:]
  • 字符串切片 — s[2:8]、s[:5](UTF-8 字符级)
  • 字符串插值 — $"Hello, {name}!" 内嵌表达式
  • 原始字符串 — @"raw string" 不转义
  • 格式化输出 — format("%02d: %-10s", i, name) C 风格格式控制
  • 并行赋值 — a, b = b, a 交换变量
  • switch 二分查找优化 — 同类型 case ≥ 4 个时自动二分查找(int/float/string),13x 加速
  • 正则表达式 — regexs 模块
  • JSON — jsons 模块编解码
  • 垃圾回收 — 内置 GC,自动内存管理,延迟回收不阻塞事件循环
  • 字节码编译 — 源码 → .lenb 字节码 → 独立 exe 打包
  • --debug 调试 — 编译完成后统一输出全部字节码(主程序 + 所有模块),行号对齐
  • LSP 语言服务器 — 代码补全、定义跳转、悬停提示
  • 跨平台 — Windows / Linux / macOS(通过 GitHub Actions 自动构建验证)

快速开始

Hello World

创建 hello.leno:

main() {
    print("Hello, Leno!")
}

运行:

leno hello.leno

更多示例

main() {
    // 类型推断
    var name = "Leno"
    var features = ["静态类型", "协程", "FFI", "模块系统"]

    // 结构体(命名参数构造)
    var p = new Point(x = 3, y = 4)
    print("距离 = " + p.dist())

    // 多返回值 + 解构
    var[int, int](lo, hi) = minMax([3, 1, 9, 7])
    print(lo, hi)  // 1, 9

    // 安全访问
    string? name2 = get_name()
    var display = name2 ?? "anonymous"

    // 链式集合操作
    var result = [1, 2, 3, 4, 5]
        .filter(func(any x, any i) { return x % 2 == 0 })
        .map(func(any x, any i) { return x * 10 })
    print(result)  // [20, 40]

    // 异常处理
    try {
        var val = 1 / 0
    } catch e {
        print("出错: " + e.msg)
    }
}

struct Point {
    int x = 0
    int y = 0
    func dist():float { return maths.sqrt(x * x + y * y) }
}

func minMax(Array[int] arr): [int, int] {
    return arr[0], arr[-1]
}

func get_name(): string? {
    return null
}

构建

前置要求

  • GCC 或 MinGW(C99 支持)

使用构建脚本

Windows:

build.bat

Linux / macOS:

chmod +x build.sh
./build.sh

构建产物 build/leno(编译器 + VM)。

构建 VM 运行时(仅 Windows)

build_vm.bat

生成 build/leno_vm.exe,只包含 VM 运行时,不含编译器前端,体积更小。

运行

# 运行 .leno 源码文件
leno hello.leno

# 运行 .lenb 字节码文件(使用 VM 运行时)
leno_vm hello.lenb

# 调试模式(输出全部字节码 + 行号)
leno --debug hello.leno

# 字节码输出到文件
leno --debug-out bytecode.txt hello.leno

# 不带参数显示帮助信息
leno

编译为字节码

Leno 支持将源码编译为 .lenb 字节码文件,然后使用 leno_vm 运行:

# 编译为字节码
leno -c hello.leno

# 运行字节码
leno_vm hello.lenb

# 打包为独立 exe
leno -p hello.leno

打包与包管理

创建包

leno --init my-package

自动生成项目结构:

my-package/
├── leno.toml              # 包配置
├── lib/
│   └── my-package.leno    # 模块代码
├── src/
│   └── main.leno          # 入口文件
├── native/                # 原生库
├── examples/              # 示例
└── test/                  # 测试

编写模块

// lib/my-package.leno
export func hello() {
    print("Hello from my-package!")
}

export var VERSION = "0.1.0"

// 导出类型别名
export alias UserID = int
export alias StrList = Array[string]

// 导出 struct
export struct Config {
    string host = "localhost"
    int port = 8080
}

// 不加 export = 私有,外部不可见
func _internal() {
    return "private"
}

安装包

# 安装本地包到全局缓存
leno --install my-package

# 从 Git 仓库安装
leno --install gitee:user/my-package

# 安装项目所有依赖(读取 leno.toml)
leno --install

使用包

import "my-package"

main() {
    my-package.hello()
    print(my-package.VERSION)
}

leno.toml 配置

[package]
name = "my-package"
version = "0.1.0"
description = "A Leno package"
license = "MIT"

[dependencies]
http_client = "~1.2.0"

[dependency-sources]
http_client = "gitee:user/http-client"

[modules]
root = "lib"

运行测试

# 运行断言测试
build/leno assert/run_tests.leno build/leno assert

命令参考

命令说明
leno显示帮助信息
leno <file.leno>运行 Leno 源码
leno --debug <file.leno>调试模式(输出全部字节码 + 行号)
leno --debug-out <file> <file.leno>字节码输出到指定文件
leno --no-cache <file.leno>禁用模块编译缓存
leno -c <file.leno>编译为 .lenb 字节码
leno -p <file.leno>打包为独立 exe
leno --init [name]创建包项目
leno --install [path]安装包到全局缓存
leno --install安装当前项目所有依赖
leno_vm <file.lenb>运行字节码文件

内置模块

模块说明
io输入输出
maths数学函数
arrays数组工具
strings字符串工具
dicts字典工具
types类型操作
times时间日期
rands随机数
files文件操作
dirs目录操作
jsonsJSON 编解码
sockets网络套接字
ffi外部函数接口
cstructsC 结构体
threads多线程
asyncs异步协程
regexs正则表达式
sys系统信息
assert断言测试

项目结构

LenoC/
├── src/
│   ├── main.c                  # 编译器入口
│   ├── module_compiler.c       # 模块编译器
│   ├── module_loader.c         # 模块加载器(含缓存)
│   ├── module_dispatch.c       # 模块分发
│   ├── parser/                 # 语法解析
│   ├── semantic/               # 语义分析
│   ├── codegen/                # 字节码生成
│   ├── vm/                     # 虚拟机
│   ├── optimize/               # 优化器
│   ├── serialize/              # 序列化/反序列化
│   ├── gc.c                    # 垃圾回收
│   ├── debug.c                 # 字节码反汇编
│   ├── module/                 # 内置模块
│   ├── module_symbol_table/    # 模块符号表
│   ├── package/                # 包管理
│   ├── object/                 # 内置对象类型
│   └── platform/               # 平台相关
├── leno_lsp/                   # LSP 语言服务器
├── leno_module/                # 内置扩展模块
│   ├── LenoSDL3/               # SDL3 GUI 框架
│   ├── LenoWeb/                # Web 模块
│   ├── LenoSqlite/             # SQLite 模块
│   ├── LenoWin32/              # Win32 API 模块
│   └── LenoMusic/              # 音乐模块
├── assert/                     # 测试用例
├── examples/                   # 示例代码
├── docs/                       # 文档
├── build.bat / build.sh        # 构建脚本
└── build_vm.bat / build_vm.sh  # VM 构建脚本

文档

许可证

MIT

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐