~boringcactus/rust-scripting-languages

0f65b28aaa181bf8a4c923c5b11dc44fe6cd6ba1 — Melody Horn 3 years ago 30461ed
write ketos example but also don't use anyhow
M Cargo.lock => Cargo.lock +224 -11
@@ 46,12 46,6 @@ dependencies = [
]

[[package]]
name = "anyhow"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"

[[package]]
name = "archery"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 273,7 267,7 @@ version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
dependencies = [
 "num",
 "num 0.1.42",
 "time",
]



@@ 454,6 448,27 @@ dependencies = [
]

[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
dependencies = [
 "cfg-if",
 "dirs-sys",
]

[[package]]
name = "dirs-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
dependencies = [
 "libc",
 "redox_users",
 "winapi 0.3.9",
]

[[package]]
name = "docopt"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1071,6 1086,26 @@ dependencies = [
]

[[package]]
name = "gumdrop"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee50908bc1beeac1f2902e0b4e0cd0d844e716f5ebdc6f0cfc1163fe5e10bcde"
dependencies = [
 "gumdrop_derive",
]

[[package]]
name = "gumdrop_derive"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90454ce4de40b7ca6a8968b5ef367bdab48413962588d0d2b1638d60090c35d7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "h2"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1298,6 1333,20 @@ dependencies = [
]

[[package]]
name = "ketos"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "986ce1fd5cca8da1220613c9eda4779f9fa70950cab3429618ca96d7adcd735e"
dependencies = [
 "byteorder",
 "dirs 2.0.2",
 "gumdrop",
 "linefeed",
 "num 0.2.1",
 "rand 0.7.3",
]

[[package]]
name = "lalrpop"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1347,6 1396,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"

[[package]]
name = "linefeed"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28715d08e35c6c074f9ae6b2e6a2420bac75d050c66ecd669d7d5b98e2caa036"
dependencies = [
 "dirs 1.0.5",
 "mortal",
 "winapi 0.3.9",
]

[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1416,7 1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79496a5651c8d57cd033c5add8ca7ee4e3d5f7587a4777484640d9cb60392d9"
dependencies = [
 "fnv",
 "nom",
 "nom 1.2.4",
]

[[package]]


@@ 1477,6 1537,22 @@ dependencies = [
]

[[package]]
name = "mortal"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "998fd6a991497275567703b6f435e27958b633878ec991f5734b96dd46675e9f"
dependencies = [
 "bitflags",
 "libc",
 "nix",
 "smallstr",
 "terminfo",
 "unicode-normalization",
 "unicode-width",
 "winapi 0.3.9",
]

[[package]]
name = "native-tls"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1512,12 1588,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"

[[package]]
name = "nix"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
dependencies = [
 "bitflags",
 "cc",
 "cfg-if",
 "libc",
 "void",
]

[[package]]
name = "nom"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"

[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
 "memchr 2.3.3",
 "version_check",
]

[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1529,6 1628,41 @@ dependencies = [
]

[[package]]
name = "num"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
 "num-bigint",
 "num-complex",
 "num-integer",
 "num-iter",
 "num-rational",
 "num-traits",
]

[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
 "autocfg 1.0.1",
 "num-integer",
 "num-traits",
]

[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
dependencies = [
 "autocfg 1.0.1",
 "num-traits",
]

[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1550,6 1684,18 @@ dependencies = [
]

[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
 "autocfg 1.0.1",
 "num-bigint",
 "num-integer",
 "num-traits",
]

[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1709,6 1855,35 @@ dependencies = [
]

[[package]]
name = "phf"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
 "phf_shared",
]

[[package]]
name = "phf_codegen"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
dependencies = [
 "phf_generator",
 "phf_shared",
]

[[package]]
name = "phf_generator"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
dependencies = [
 "phf_shared",
 "rand 0.7.3",
]

[[package]]
name = "phf_shared"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1857,7 2032,7 @@ dependencies = [
 "rand_isaac",
 "rand_jitter",
 "rand_os",
 "rand_pcg",
 "rand_pcg 0.1.2",
 "rand_xorshift 0.1.1",
 "winapi 0.3.9",
]


@@ 1873,6 2048,7 @@ dependencies = [
 "rand_chacha 0.2.2",
 "rand_core 0.5.1",
 "rand_hc 0.2.0",
 "rand_pcg 0.2.1",
]

[[package]]


@@ 1982,6 2158,15 @@ dependencies = [
]

[[package]]
name = "rand_pcg"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
dependencies = [
 "rand_core 0.5.1",
]

[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2173,12 2358,12 @@ dependencies = [
name = "rust-scripting-languages"
version = "0.1.0"
dependencies = [
 "anyhow",
 "duckscript",
 "duckscriptsdk",
 "dyon",
 "gluon",
 "gluon_codegen",
 "ketos",
 "rhai",
 "rlua",
]


@@ 2350,6 2535,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"

[[package]]
name = "smallstr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f"
dependencies = [
 "smallvec 1.4.2",
]

[[package]]
name = "smallvec"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2448,7 2642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
dependencies = [
 "byteorder",
 "dirs",
 "dirs 1.0.5",
 "winapi 0.3.9",
]



@@ 2462,6 2656,19 @@ dependencies = [
]

[[package]]
name = "terminfo"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76971977e6121664ec1b960d1313aacfa75642adc93b9d4d53b247bd4cb1747e"
dependencies = [
 "dirs 2.0.2",
 "fnv",
 "nom 5.1.2",
 "phf",
 "phf_codegen",
]

[[package]]
name = "thiserror"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2827,6 3034,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"

[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"

[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +8 -4
@@ 4,9 4,6 @@ version = "0.1.0"
authors = ["Melody Horn <melody@boringcactus.com>"]
edition = "2018"

[dependencies]
anyhow = "1.0.32"

[dependencies.rlua]
version = "0.17.0"
optional = true


@@ 30,7 27,6 @@ required-features = ["duckscript", "duckscriptsdk"]
[dependencies.rhai]
version = "0.18.3"
optional = true
features = ["sync"]

[[example]]
name = "rhai"


@@ 55,3 51,11 @@ optional = true
[[example]]
name = "gluon"
required-features = ["gluon", "gluon_codegen"]

[dependencies.ketos]
version = "0.12.0"
optional = true

[[example]]
name = "ketos"
required-features = ["ketos"]

M examples/duckscript.rs => examples/duckscript.rs +8 -9
@@ 2,6 2,7 @@ use duckscript::{
    runner::run_script_file,
    types::{
        command::{Command, CommandResult},
        error::ScriptError,
        runtime::Context,
    },
};


@@ 30,20 31,19 @@ struct DuckscriptHost;

impl ScriptHost for DuckscriptHost {
    type ScriptContext = ();
    type Error = ScriptError;

    fn new_context() -> anyhow::Result<Self::ScriptContext> {
    fn new_context() -> Result<Self::ScriptContext, ScriptError> {
        Ok(())
    }

    fn handle_event(_context: &mut Self::ScriptContext, event: Event) -> anyhow::Result<()> {
    fn handle_event(_context: &mut Self::ScriptContext, event: Event) -> Result<(), ScriptError> {
        // Make a context
        let mut context = Context::new();
        // Add the standard library
        duckscriptsdk::load(&mut context.commands)
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        duckscriptsdk::load(&mut context.commands)?;
        // Add our print_fancy command
        context.commands.set(Box::new(PrintFancyCommand))
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        context.commands.set(Box::new(PrintFancyCommand))?;
        // Pick some strings to put in the context to represent our event
        let (event_type, event_value) = match event {
            Event::Number(value) => ("number", format!("{}", value)),


@@ 52,12 52,11 @@ impl ScriptHost for DuckscriptHost {
        context.variables.insert("event.type".to_string(), event_type.to_string());
        context.variables.insert("event.value".to_string(), event_value);
        // Run the script
        run_script_file("scripts/duckscript-sample.ds", context)
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        run_script_file("scripts/duckscript-sample.ds", context)?;
        Ok(())
    }
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<(), ScriptError> {
    run_main::<DuckscriptHost>()
}

M examples/dyon.rs => examples/dyon.rs +7 -8
@@ 3,7 3,7 @@ extern crate dyon;

use std::sync::Arc;

use dyon::{Call, Dfn, load, Module, Runtime, Type};
use dyon::{Call, Dfn, Error, load, Module, Runtime, Type};

use rust_scripting_languages::*;



@@ 11,8 11,9 @@ struct DyonScriptHost;

impl ScriptHost for DyonScriptHost {
    type ScriptContext = Arc<Module>;
    type Error = Error;

    fn new_context() -> anyhow::Result<Self::ScriptContext> {
    fn new_context() -> Result<Self::ScriptContext, Error> {
        let mut module = Module::new();

        dyon_fn!{fn dyon_print_fancy(x: String) {


@@ 20,26 21,24 @@ impl ScriptHost for DyonScriptHost {
        }}
        module.add_str("print_fancy", dyon_print_fancy, Dfn::nl(vec![Type::Str], Type::Void));

        load("scripts/dyon-sample.dyon", &mut module)
            .map_err(|x| anyhow::anyhow!("{}", x))?;
        load("scripts/dyon-sample.dyon", &mut module)?;

        Ok(Arc::new(module))
    }

    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> anyhow::Result<()> {
    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> Result<(), Error> {
        let call = Call::new("handle_event");
        let call = match event {
            Event::Number(value) => call.arg(value as f64),
            Event::Text(value) => call.arg(value),
        };

        call.run(&mut Runtime::new(), context)
            .map_err(|x| anyhow::anyhow!("{}", x))?;
        call.run(&mut Runtime::new(), context)?;

        Ok(())
    }
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<(), Error> {
    run_main::<DyonScriptHost>()
}

M examples/gluon.rs => examples/gluon.rs +5 -3
@@ 4,6 4,7 @@ extern crate gluon_codegen;
use std::fs::read_to_string;

use gluon::{
    Error,
    import::add_extern_module,
    new_vm,
    primitive,


@@ 35,8 36,9 @@ struct GluonScriptHost;

impl ScriptHost for GluonScriptHost {
    type ScriptContext = RootedThread;
    type Error = Error;

    fn new_context() -> anyhow::Result<Self::ScriptContext> {
    fn new_context() -> Result<Self::ScriptContext, Error> {
        let vm = new_vm();

        fn load_print_fancy(vm: &Thread) -> vm::Result<vm::ExternModule> {


@@ 56,7 58,7 @@ impl ScriptHost for GluonScriptHost {
        Ok(vm)
    }

    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> anyhow::Result<()> {
    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> Result<(), Error> {
        let mut handle_event: vm::api::FunctionRef<fn (EventForGluon)> = context.get_global("handle_event")
            .unwrap();
        handle_event.call(event.into())?;


@@ 65,6 67,6 @@ impl ScriptHost for GluonScriptHost {
    }
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<(), Error> {
    run_main::<GluonScriptHost>()
}

A examples/ketos.rs => examples/ketos.rs +43 -0
@@ 0,0 1,43 @@
use std::path::PathBuf;

use ketos::{Error, Interpreter, ketos_fn, Value};

use rust_scripting_languages::*;

struct KetosScriptHost;

impl ScriptHost for KetosScriptHost {
    type ScriptContext = Interpreter;
    type Error = Error;

    fn new_context() -> Result<Self::ScriptContext, Error> {
        let interp = Interpreter::new();

        let scope = interp.scope();

        fn print_fancy_fallible(text: &str) -> Result<(), Error> {
            print_fancy(text);
            Ok(())
        }

        ketos_fn! { scope => "print-fancy" => fn print_fancy_fallible(text: &str) -> () }

        interp.run_file(&PathBuf::from("scripts/ketos-sample.ket"))?;

        Ok(interp)
    }

    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> Result<(), Error> {
        let value = match event {
            Event::Number(n) => Value::from(n),
            Event::Text(t) => Value::from(t),
        };
        context.call("handle-event", vec![value])?;

        Ok(())
    }
}

fn main() -> Result<(), Error> {
    run_main::<KetosScriptHost>()
}

M examples/rhai.rs => examples/rhai.rs +5 -4
@@ 1,6 1,6 @@
use std::path::PathBuf;

use rhai::{AST, Dynamic, Engine, RegisterFn, Scope};
use rhai::{AST, Dynamic, Engine, EvalAltResult, RegisterFn, Scope};

use rust_scripting_languages::*;



@@ 8,8 8,9 @@ struct RhaiScriptHost;

impl ScriptHost for RhaiScriptHost {
    type ScriptContext = (Engine, Scope<'static>, AST);
    type Error = Box<EvalAltResult>;

    fn new_context() -> anyhow::Result<Self::ScriptContext> {
    fn new_context() -> Result<Self::ScriptContext, Self::Error> {
        let mut engine = Engine::new();
        engine.register_fn("print_fancy", print_fancy);
        let mut scope = Scope::new();


@@ 20,7 21,7 @@ impl ScriptHost for RhaiScriptHost {
        Ok((engine, scope, ast))
    }

    fn handle_event((engine, scope, ast): &mut Self::ScriptContext, event: Event) -> anyhow::Result<()> {
    fn handle_event((engine, scope, ast): &mut Self::ScriptContext, event: Event) -> Result<(), Self::Error> {
        let argument = match event {
            Event::Number(number) => Dynamic::from(number),
            Event::Text(text) => Dynamic::from(text),


@@ 30,6 31,6 @@ impl ScriptHost for RhaiScriptHost {
    }
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<(), Box<EvalAltResult>> {
    run_main::<RhaiScriptHost>()
}

M examples/rlua.rs => examples/rlua.rs +8 -7
@@ 1,6 1,6 @@
use std::fs::read_to_string;

use rlua::{Function, Lua, Nil, ToLua, UserData, UserDataMethods};
use rlua::{Error, Function, Lua, Nil, ToLua, UserData, UserDataMethods};

use rust_scripting_languages::*;



@@ 28,10 28,11 @@ struct LuaScriptHost;

impl ScriptHost for LuaScriptHost {
    type ScriptContext = Lua;
    type Error = Error;

    fn new_context() -> anyhow::Result<Lua> {
    fn new_context() -> Result<Lua, Error> {
        let lua = Lua::new();
        lua.context::<_, anyhow::Result<()>>(|lua_ctx| {
        lua.context::<_, Result<(), Error>>(|lua_ctx| {
            let print_fancy = lua_ctx.create_function(|_, text: String| {
                print_fancy(&text);
                Ok(())


@@ 41,7 42,7 @@ impl ScriptHost for LuaScriptHost {
                .set("print_fancy", print_fancy)?;

            lua_ctx
                .load(&(read_to_string("scripts/rlua-sample.lua")?))
                .load(&(read_to_string("scripts/rlua-sample.lua").unwrap()))
                .set_name("rlua-sample.lua")?
                .exec()?;



@@ 50,8 51,8 @@ impl ScriptHost for LuaScriptHost {
        Ok(lua)
    }

    fn handle_event(context: &mut Lua, event: Event) -> anyhow::Result<()> {
        context.context::<_, anyhow::Result<()>>(|lua_ctx| {
    fn handle_event(context: &mut Lua, event: Event) -> Result<(), Error> {
        context.context::<_, Result<(), Error>>(|lua_ctx| {
            let handle_event: Function = lua_ctx.globals().get("handle_event")?;
            handle_event.call::<_, ()>(EventForLua(event))?;



@@ 62,6 63,6 @@ impl ScriptHost for LuaScriptHost {
    }
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<(), Error> {
    run_main::<LuaScriptHost>()
}

A scripts/ketos-sample.ket => scripts/ketos-sample.ket +4 -0
@@ 0,0 1,4 @@
(define (handle-event event)
    (do
        (println "~a ~a" (type-of event) event)
        (print-fancy "got an event!")))

M src/lib.rs => src/lib.rs +5 -4
@@ 11,13 11,14 @@ pub fn print_fancy(text: &str) {

pub trait ScriptHost {
    type ScriptContext;
    type Error;

    fn new_context() -> anyhow::Result<Self::ScriptContext>;
    fn new_context() -> Result<Self::ScriptContext, Self::Error>;

    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> anyhow::Result<()>;
    fn handle_event(context: &mut Self::ScriptContext, event: Event) -> Result<(), Self::Error>;
}

pub fn run_main<SH: ScriptHost>() -> anyhow::Result<()> {
pub fn run_main<SH: ScriptHost>() -> Result<(), SH::Error> {
    let stdin = stdin();

    let mut context = SH::new_context()?;


@@ 25,7 26,7 @@ pub fn run_main<SH: ScriptHost>() -> anyhow::Result<()> {
    loop {
        println!("Type a number or some text to fire an event, or nothing to exit.");
        let mut input = String::new();
        stdin.read_line(&mut input)?;
        stdin.read_line(&mut input).unwrap();
        let input = input.trim();

        if input.is_empty() {