A Rust implementation of the Egg Programming Language

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

Docs | Repo

##### `egg` is a toy Programming Language from the book Eloquent Javascript by Marijn Haverbeke, [Chapter 12](https://eloquentjavascript.net/12_language.html). The Book was pivotal to my early Programming journey. I moved to Rust some time back and in a fit of nostalgia I decided to rewrite `egg` in Rust. ### ✨ Features - **Extensive** and **Modular** standard library; `Core`, `Objects`, `StringTools`, `Console` and `Functions` - **Effective Scope Chain**: Local Variables and Global Variables work as expected. - **User-Defined Functions**: Create functions in Egg using the `fn` keyword. - **Higher Order Functions**: Pass functions as values to other functions or to built-in `Operators`. - **Extensible**: Create your own builtin functions by implementing the [`Operator`](https://docs.rs/egglang/latest/egglang/operators/trait.Operator.html) trait. - **no_std**: Only depends on `alloc`. Enabling the `std` feature adds the `Print`, `PrintLine`, `ReadLine` and `Sleep` builtins. ### 🏋️‍♂️ Examples ##### To start executing a script, we need to first `parse` it, create a `Scope` and assemble a map of builtin functions it can access: ```rust 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()); ``` ##### We can also define custom built-in functions by implementing `Operator` on a type: ```rust 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>) -> EggResult { // 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(); } ``` > Example Egg scripts can be found in the `scripts` directory;

Credit: u/Penguin-warrior-3105