#scripting #interpreter #scripting-language #egg #programming-language #language #parser

no-std egglang

来自《Eloquent JavaScript》的Egg编程语言,但使用Rust编写

6个版本

0.3.2 2024年5月11日
0.3.1 2024年5月11日
0.2.0 2022年12月1日
0.1.5 2022年11月15日

#109 in 编程语言

MIT 许可证

59KB
1K SLoC

A Rust实现Egg编程语言

Crate Version on Crates.io docs.rs
GitHub GitHub issues

文档 | 仓库

egg 是来自 Marijn Haverbeke 的《Eloquent Javascript》一书中的一本玩具编程语言,第12章。这本书对我的早期编程之旅至关重要。我之前一段时间转向了 Rust,出于怀旧之情,我决定用 Rust 重新编写 egg

✨ 特性

  • 广泛模块化 的标准库;CoreObjectsStringToolsConsoleFunctions
  • 有效的作用域链:局部变量和全局变量按预期工作。
  • 用户定义函数:使用 fn 关键字在 Egg 中创建函数。
  • 高阶函数:将函数作为值传递给其他函数或内置的 Operators
  • 可扩展性:通过实现 Operator trait 创建自己的内置函数。
  • no_std:仅依赖于 alloc。启用 std 功能会添加 PrintPrintLineReadLineSleep 内置函数。

🏋️‍♂️ 示例

要开始执行脚本,我们首先需要解析它,创建一个 Scope 并组装一个它可以访问的内置函数映射
use egglang::prelude::*;

// Create the default Scope, with necessary constants set
let mut scope = Scope::default();

// Create a minimal set of operators
let mut operators = operators::empty();
operators::minimal(&mut operators);

// Parse a Script into a list of expressions
let script = "sum(12.5, 12.5, 25)";
let expressions = parse(script).unwrap();

// Evaluate the expression
let expression = &expressions[0]; // the call to `sum`
let result = evaluate(expression, &mut scope, &operators).unwrap();

assert_eq!(result, 50f32.into());
我们也可以通过在类型上实现 Operator 定义自定义的内置函数
use egglang::prelude::*;
use std::collections::BTreeMap;

// Create the default Scope, with necessary constants set
let mut scope = Scope::default();

// Insert base operators, and add console functions; Adds println
let mut operators = operators::empty();
operators::minimal(&mut operators);
operators::console(&mut operators);

// Define a `random(...)` builtin
struct Random;

impl Operator for Random {
    	fn evaluate(&self, _: &[Expression], _: &mut Scope, _: &BTreeMap<&str, Box<dyn Operator>>) -> EggResult<Value> {
    		// totally random value ;)
    		Ok(0.15.into())
    }
}

// Insert `random(...)` into Operators map
operators.insert("random", Box::new(Random));

// Parse a Script into a list of expressions
let script = r#"
define(iterations, random(0, 120))
repeat(iterations, println("oi oi oi oi oi"))
"#;
let expressions = parse(script).unwrap();

// Evaluate the expressions; define -> repeat -> ...
for expression in expressions {
  let _ = evaluate(&expression, &mut scope, &operators).unwrap();
}

示例 Egg 脚本可以在 scripts 目录中找到;

来源: u/Penguin-warrior-3105

依赖项

~3.5MB
~42K SLoC