#scripting #lox #parser #control-flow

rulox

A lightweight scripting language embedded in Rust

17 unstable releases (8 breaking)

0.9.0 Nov 28, 2023
0.7.2 Feb 17, 2023

#517 in Parser implementations

MIT license

135KB
3K SLoC

rulox

crates.io github docs.rs

rulox is a lightweight scripting language embedded in Rust. It is based on the Lox language from Crafting Interpreters.

Basic use

Add use rulox::prelude::* at the top level of each module you want to use rulox in, then invoke the lox macro with your Lox code. Note that due to technical limitations, the lox macro can currently only be used in functions that return Result<_, LoxError>.

Examples

use rulox::prelude::*;
use rulox::LoxError;

fn main() -> Result<(), LoxError> {
    lox! {
        var a = 5;

        print a + 2;
    }

    let b: f64 = a.get()?.try_into().unwrap();

    println!("{}", b);

    Ok(())
}
lox! {
    for (var i = 5; i > 0; i = i - 1) print i;
}
lox! {
   fun hello(name) {
        print "Hello " + name + "! :)";
   }

    fun add_one(num) {
        return num + 1;
    }
}

hello.get()?.call([LoxValue::from("Alice")].into());

assert_eq!(add_one.get()?.call([LoxValue::from(3)].into())?, 4);
lox! {
    var people = ["Bob", "Alice", "John"];

    for (person in people) {
        print "Hello " + person + "!";
    }
}
lox! {
    class Person {
        init(name) {
            this.name = name;
        }

        say_hello() {
            print "Hello, my name is " + this.name + "!";
        }
    }

    var jane = Person("Jane");
    jane.say_hello();
}
lox! {
    class Person {
        init(name) {
            this.name = name;
        }

        say_hello() {
            print "Hello, my name is " + this.name + "!";
        }
    }

    class Telepath > Person {
        init(name, power) {
            super(name);
            this.power = power;
        }

        lift(weight) {
            if (this.power < weight) {
                print "It's too heavy!";
            } else if (this.power == weight) {
                print "I can't keep this up for long!";
            } else {
                print "This is child's play.";
            }
        }
    }

    var bob = Person("Bob");
    bob.say_hello();

    print "";

    var alice = Telepath("Alice", 4);
    alice.say_hello();
    alice.lift(1.5);
    alice.lift(4);
    alice.lift(10);
}
lox! {
    var except_ran = false;
    var else_ran = false;
    var finally_ran = false;
    try {
        print "try";
        throw 1;
    } except {
        print "except";
        except_ran = true;
    } else {
        print "else";
        else_ran = true;
    } finally {
        print "finally";
        finally_ran = true;
    }
}

Features

  • Variable declarations
  • Print statements
  • Control flow statements
  • Loops
  • for ... in ... loops
  • Indefinite loops and break
  • Functions as first-class objects
  • Object orientation
  • Closures
  • Error handling
  • Async/await
  • Hashmaps

Possible future features

  • Macros

Dependencies

~0.5–1.1MB
~24K SLoC