I wrote a scripting language in Rust that I use for all my game dev projects.

It’s statically typed but with type inference, has an incremental garbage collector, and compiles down to a bytecode I wrote so that it can be executed by a virtual machine I also wrote in Rust. This makes it super easy to hot swap out scripts in game without reloading the whole game, and also made it pretty easy to set up a read eval print loop. I’m not ready to release it publicly yet, but here’s a few snippets to show it off:

use dbg;

fn main() {
    dbg::println("Hello, world!");

It’s expression based, if/else statements for example result in values that can be stored in variables or returned:

fn factorial(n: int) -> int {
    if n > 1 {
        n * factorial(n - 1)
    } else {

It’s easy to interface with the language from Rust:

// Define a Rust marker type for a type that will be defined in a script
// so that we can pass it to Rust.

fn main() {
    // Create a new virtual machine to run the code in
    let mut vm = Vm::new();

    // Compile the geometry module from source
    vm.load_string("geom", r"
        pub struct Point::<T> {
            pub x: T,
            pub y: T,

    // Create an instance of `Point` in the script and pass it to Rust
    let origin: Managed<Point<Ratio>> =
        vm.repl("@Point::<ratio> { x: int, y: int }")

    // ...now we're free to store the point, pass it back into other functions
    // defined in the script, etc

And much more…

use dbg::println;

struct Vec2 {
    x: ratio,
    y: ratio,

// These vecs are passed in as immutable garbage collected references
fn dot(a: @Vec2, b: @Vec2) -> ratio {
    a.x * b.x + a.y * b.y

// On the other hand, this vec is passed in as a mutable garbage collected
// reference
fn scale(v: @mut Vec2, s: ratio) {
    a.x * b.x + a.y * b.y

fn main() {
    let a = @mut Vec2 { x: 1.0, y: 2.0 };
    let b = @mut Vec2 { x: 3.0, y: 4.0 };

    let dot = dot(a, b); // If not specified, the types of locals are inferred
    scale(a, dot);

    // Support for sum types!

enum Option::<T> {

fn print_option_i32(n: Option::<i32>) {
    match n {
        Some(x) => println(f"The value is {x}!"),
        None => println("no value :("),