Rust ยท scripting language

A language small
enough to read whole.

Sprite is a tiny, embeddable scripting language in Rust. Lexer, parser, tree-walking interpreter, one eval call to drop into any Rust program. Try it below, right in your browser.

View on GitHub Language tour

Try a subset in your browser

This box runs a small JavaScript reimplementation of a subset of Sprite (expressions, let, print, if/else, while) so you can poke at the syntax here. The real interpreter is the Rust crate.

runs entirely in your browser, nothing is sent anywhere
Click Run to evaluate the script above.

Small on purpose

Lua and Rhai are excellent and much more capable. Sprite is the other end of the spectrum: a scripting language in Rust small enough that reading the whole interpreter is a reasonable way to spend an afternoon.

Read in a sitting

Lexer, parser, and interpreter are a few hundred lines each. No bytecode compiler, no VM, no parser generator.

One eval call

sprite::eval(source) returns a Value. A Session keeps state alive across calls for a REPL or a long-lived embedding.

Never panics on bad input

Lex, parse, and runtime errors are all typed results. Deeply nested or hostile input returns an error, not a crash.

Language tour

Variables, arithmetic, comparisons, booleans, control flow, functions, closures, and string concatenation.

# variables and arithmetic
let x = 2 + 3 * 4
print(x)                    # 14

# recursive functions
fn fact(n) {
    if n <= 1 {
        return 1
    }
    return n * fact(n - 1)
}
print(fact(5))               # 120

# while loops
let i = 1
let sum = 0
while i <= 10 {
    sum = sum + i
    i = i + 1
}
print(sum)                    # 55

# closures
fn make_counter() {
    let count = 0
    fn increment() {
        count = count + 1
        return count
    }
    return increment
}
let counter = make_counter()
print(counter())              # 1
print(counter())              # 2

Embedding

A clean API for dropping a scripting layer into any Rust program.

One-shot

let value = sprite::eval(
    "2 + 3 * 4"
).unwrap();

assert_eq!(
    value.to_string(),
    "14"
);

Persistent session

let mut s = sprite::Session::new();
s.run("let score = 0").unwrap();
s.run("score = score + 10").unwrap();

let v = s.run("score").unwrap();
assert_eq!(v.to_string(), "10");