| Crates.io | aether-azathoth |
| lib.rs | aether-azathoth |
| version | 0.5.3 |
| created_at | 2025-11-08 12:56:59.326348+00 |
| updated_at | 2026-01-16 05:31:03.38879+00 |
| description | A lightweight, embeddable domain-specific language (DSL) interpreter with rich standard library |
| homepage | https://github.com/xiaozuhui/aether |
| repository | https://github.com/xiaozuhui/aether |
| max_upload_size | |
| id | 1922838 |
| size | 1,117,217 |
Aether 是一个现代化、轻量级的脚本语言,设计用于嵌入到 Rust、Go 和 TypeScript 应用程序中。
# Rust 库
cargo add aether
# 命令行工具
cargo install aether
# Go
go get github.com/yourusername/aether-go
# TypeScript/aether
npm install @yourusername/aether
命令行 (IO 自动启用):
# 创建 hello.aether
echo 'PRINTLN("Hello, Aether!")' > hello.aether
# 运行
aether hello.aether
Rust 嵌入 (默认安全):
use aether::Aether;
fn main() {
let mut engine = Aether::new(); // IO 默认禁用
let result = engine.eval(r#"
Set X 10
Set Y 20
(X + Y)
"#).unwrap();
println!("结果: {}", result); // 输出: 30
}
启用 IO (可选):
use aether::{Aether, IOPermissions};
// 完全启用 IO
let mut engine = Aether::with_all_permissions();
// 或仅启用文件系统
let permissions = IOPermissions {
filesystem_enabled: true,
network_enabled: false,
};
let mut engine = Aether::with_permissions(permissions);
engine.eval(r#"
WRITE_FILE("output.txt", "Hello!")
PRINTLN(READ_FILE("output.txt"))
"#).unwrap();
在 DSL 场景下通常会禁用 IO(不能 PRINT/PRINTLN/INPUT),但你仍然可以通过 TRACE(...) 安全记录调试信息:
TRACE(...) 不会写 stdout / 文件 / 网络take_trace() 读取并自行输出/写日志补充:
#1 ..., #2 ...TRACE("label", x, y) 会记录为 [#N] [label] x ySet X [1, 2, 3]
Set Y {"a": 12}
Set Z (Y["a"] + 3)
TRACE("X=" + TO_STRING(X))
TRACE({"y": Y, "z": Z})
Z
Rust 侧读取 trace:
use aether::Aether;
fn main() -> Result<(), String> {
let mut engine = Aether::new(); // DSL 模式:默认无 IO
let v = engine.eval(r#"
Set X [1, 2, 3]
TRACE("hello")
TRACE(X)
42
"#)?;
let trace = engine.take_trace();
// 这里由宿主决定如何处理(打印/结构化日志/埋点)
// e.g. ["#1 hello", "#2 [dbg] 1 2", ...]
println!("trace={:?}", trace);
println!("result={}", v);
Ok(())
}
Import/Export 的运行时模块系统已实现,但 DSL 场景默认禁用导入(安全优先)。
在 DSL 工程里仍更推荐 B 方案:由宿主统一管理“模块/函数库”(例如从数据库取出 Aether 函数定义),在每次执行前注入。
为支持“像 PyO3 一样把数据/函数放到 globals,然后执行脚本,并且执行完自动清空不污染”,引擎提供:
engine.set_global(name, Value):直接注入 Rust 侧数据(无需 eval)engine.with_isolated_scope(|engine| ...):闭包作用域,闭包结束后自动丢弃本次注入/定义engine.reset_env():强制清空整个环境(会清掉通过 eval 加载的 stdlib/函数)在通用语言/CLI 场景下,你可以使用 Import/Export 把代码拆成多个 .aether 文件。
Aether::new())默认 resolver 为禁用:脚本里 Import 会报错As(也兼容旧写法 as)Import M From "./math" 会把模块导出绑定为一个 Dict 到 M(可用 M["ADD"] 访问){}:例如 Import {ADD} From "./math"(避免与命名空间导入歧义)最小示例见:
命令行运行:
aether examples/module_import/main.aether
Rust 侧以文件方式执行(方案1:eval_file 只管理 base_dir,上层显式启用 resolver):
use aether::{Aether, FileSystemModuleResolver};
fn main() -> Result<(), String> {
let mut engine = Aether::new();
engine.set_module_resolver(Box::new(FileSystemModuleResolver::default()));
engine.eval_file("examples/module_import/main.aether")?;
Ok(())
}
更多设计与规划:
最小示例:Rust 数据 + DB 函数 + 脚本(闭包结束自动清理):
use aether::{Aether, Value};
use std::collections::HashMap;
fn main() -> Result<(), String> {
let mut engine = Aether::new(); // DSL:默认无 IO
// 模拟从 DB 取出来的一堆 Aether 函数定义
let db_funcs: Vec<String> = vec![
r#"Func ADD_TAX (amount, rate) { Return (amount * (1 + rate)) }"#.to_string(),
r#"Func APPLY_DISCOUNT (subtotal, coupon) { Return (subtotal - coupon) }"#.to_string(),
];
let script = r#"
Set net APPLY_DISCOUNT(INPUT[\"subtotal\"], INPUT[\"coupon\"])
ADD_TAX(net, RATE)
"#;
let out = engine.with_isolated_scope(|engine| {
// 注入 Rust 数据(不用 eval)
engine.set_global("RATE", Value::Number(0.08));
let mut input = HashMap::new();
input.insert("subtotal".to_string(), Value::Number(1000.0));
input.insert("coupon".to_string(), Value::Number(50.0));
engine.set_global("INPUT", Value::Dict(input));
// 注入 DB 函数(逐条 eval)
for f in &db_funcs {
engine.eval(f)?;
}
// 执行脚本
engine.eval(script)
})?;
println!("out={}", out);
Ok(())
}
// 变量 (必须 UPPER_SNAKE_CASE)
Set COUNT 10
Set MESSAGE "Hello, Aether"
Set NUMBERS [1, 2, 3, 4, 5]
Set USER {"name": "Alice", "age": 30}
// 函数
Func ADD (A, B) {
Return (A + B)
}
Set RESULT ADD(5, 3)
PRINTLN("5 + 3 =", RESULT)
// If-Else
Func ABS (X) {
If (X < 0) {
Return (0 - X)
} Else {
Return X
}
}
// For 循环
For I In RANGE(0, 5) {
PRINTLN("数字:", I)
}
// While 循环
Set I 0
While (I < 5) {
PRINTLN(I)
Set I (I + 1)
}
Generator FIBONACCI (LIMIT) {
Set A 0
Set B 1
Set COUNT 0
While (COUNT < LIMIT) {
Yield A
Set NEXT (A + B)
Set A B
Set B NEXT
Set COUNT (COUNT + 1)
}
}
// 使用
For NUM In FIBONACCI(10) {
PRINTLN(NUM)
}
// 延迟计算,仅在需要时执行
Lazy EXPENSIVE_DATA (
PRINTLN("正在加载大数据集...")
Return READ_FILE("big_data.json")
)
// 数据仅在访问时加载
If (NEEDS_ANALYSIS) {
Set DATA EXPENSIVE_DATA // 此时才执行
PROCESS(DATA)
}
// 问题:浮点精度
Set A 0.1
Set B 0.2
PRINTLN(A + B) // 可能显示: 0.30000000000000004
// 解决方案:分数运算(精确)
Set FA TO_FRACTION(0.1)
Set FB TO_FRACTION(0.2)
Set FC FRAC_ADD(FA, FB)
PRINTLN(FC) // 显示: 3/10
PRINTLN(TO_FLOAT(FC)) // 显示: 0.3
// 金融计算(固定精度)
Set PRICE1 19.99
Set PRICE2 29.99
Set TOTAL ADD_WITH_PRECISION(PRICE1, PRICE2, 2)
PRINTLN(TOTAL) // 显示: 49.98
Set TAX MUL_WITH_PRECISION(TOTAL, 0.08, 2)
PRINTLN(TAX) // 显示: 4.00
// CLI 模式:自动工作
WRITE_FILE("data.txt", "Hello, World!")
Set CONTENT READ_FILE("data.txt")
PRINTLN(CONTENT)
If FILE_EXISTS("data.txt") {
PRINTLN("文件存在!")
DELETE_FILE("data.txt")
}
// 目录操作
CREATE_DIR("output")
Set FILES LIST_DIR(".")
For FILE In FILES {
PRINTLN(FILE)
}
// HTTP GET
Set RESPONSE HTTP_GET("https://api.github.com")
PRINTLN(RESPONSE)
// HTTP POST
Set DATA '{"name": "test"}'
Set RESULT HTTP_POST(
"https://api.example.com/data",
DATA,
"application/json"
)
PRINTLN(RESULT)
// 错误示例
Set myVar 10
// ❌ 错误: 变量名必须使用全大写字母和下划线
// 正确: Set MY_VAR 10
Set RESULT (X + Y
// ❌ 错误: Parse error at line 1, column 18: Expected RightParen
// 正确
Set RESULT (X + Y)
| 模式 | IO 状态 | 使用场景 |
|---|---|---|
| CLI | 默认启用 | 直接运行脚本,用户明确信任 |
| 库 | 默认禁用 | 嵌入应用,脚本可能不可信 |
use aether::{Aether, IOPermissions};
// 1. 无 IO(最安全,默认)
let mut engine = Aether::new();
// 2. 仅文件系统
let permissions = IOPermissions {
filesystem_enabled: true,
network_enabled: false,
};
let mut engine = Aether::with_permissions(permissions);
// 3. 完全权限
let mut engine = Aether::with_all_permissions();
所有变量、函数、参数必须使用 UPPER_SNAKE_CASE:
// ✅ 正确
Set MY_VARIABLE 10
Func CALCULATE_TOTAL (PRICE, TAX_RATE) { }
// ❌ 错误
Set myVariable 10 // 会报错
Func calculateTotal () // 会报错
Aether 引入了多项性能优化:
自动缓存已解析的代码,避免重复解析:
let mut engine = Aether::new();
let code = "Set X 10\n(X + 20)";
// 第一次:解析 + 执行
engine.eval(code)?; // ~400µs
// 第二次:缓存命中 + 执行
engine.eval(code)?; // ~2.8µs (142x 快!)
// 查看缓存统计
println!("{}", engine.cache_stats());
// 输出: 命中率: 50.0%, 加速比: 142x
编译时计算常量表达式:
// 优化前
Set X (2 + 3 * 4)
// 优化后(自动)
Set X 14
移除永不执行的代码:
// 优化前
While False {
PRINTLN("永远不执行")
}
// 优化后(自动删除整个循环)
let mut engine = Aether::new();
// 控制优化
engine.set_optimization(
true, // 常量折叠
true, // 死代码消除
false // 尾递归优化(部分完成)
);
Aether 提供完整的 Go 语言绑定,支持线程安全、变量操作、追踪调试等高级功能。
详情请见 Aether-GO
import { Aether } from '@yourusername/aether';
async function main() {
const engine = new Aether();
await engine.init();
const result = engine.eval(`
Set X 10
Set Y 20
Return (X + Y)
`);
console.log('Result:', result); // 30
}
main();
# 克隆仓库
git clone https://github.com/yourusername/aether.git
cd aether
# 构建
cargo build --release
# 运行测试
cargo test
# 运行所有测试(包括集成测试)
cargo test --all
# 运行所有基准测试
cargo bench
# 查看结果
open target/criterion/report/index.html
# 快速基准测试
./scripts/bench.sh quick
# 特定类别
./scripts/bench.sh arithmetic
基准覆盖:
PRINT, PRINTLN, INPUT
READ_FILE, WRITE_FILE, APPEND_FILE
DELETE_FILE, FILE_EXISTS, CREATE_DIR
LIST_DIR, DELETE_DIR, FILE_SIZE
HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_DELETE
TO_STRING, TO_NUMBER, TYPE_OF
TO_ARRAY, TO_DICT, IS_NULL
PUSH, POP, SHIFT, UNSHIFT
MAP, FILTER, REDUCE, SORT
FIND, INCLUDES, JOIN, SLICE
LEN, SPLIT, TRIM, UPPER, LOWER
REPLACE, SUBSTRING, STARTS_WITH, ENDS_WITH
ABS, SQRT, POW, SIN, COS, TAN
MIN, MAX, SUM, AVG, MEDIAN
STDEV, VARIANCE, CORRELATION
LINEAR_REGRESSION, MATRIX_INVERSE
TO_FRACTION, FRAC_ADD, FRAC_SUB
FRAC_MUL, FRAC_DIV, TO_FLOAT
ADD_WITH_PRECISION, SUB_WITH_PRECISION
MUL_WITH_PRECISION, DIV_WITH_PRECISION
// 基本工资
HOURLY_TO_DAILY, DAILY_TO_MONTHLY
MONTHLY_TO_ANNUAL, ANNUAL_TO_MONTHLY
// 加班费
CALC_WEEKDAY_OVERTIME // 1.5x
CALC_WEEKEND_OVERTIME // 2x
CALC_HOLIDAY_OVERTIME // 3x
// 个税
CALC_PERSONAL_TAX // 7级累进
CALC_BONUS_TAX // 年终奖税
// 社保
CALC_SOCIAL_INSURANCE
CALC_HOUSING_FUND
已完成:
计划中:
根据 GNU General Public License Version 3 (GPLv3) 许可,附加例外条款(LICENSE)。
注意:所有为该项目添加代码的成员都必须签署DCO协议DCO
Aether 的灵感来自:
由 Aether 贡献者用 ❤️ 制作