ketos 0.12.0

Lisp dialect scripting and extension language
Documentation
#[macro_use] extern crate assert_matches;

extern crate ketos;
#[macro_use] extern crate ketos_derive;

use ketos::{Error, ExecError, FromValue, Interpreter, Value};

#[derive(Clone, Debug, ForeignValue, StructValue)]
struct Foo {
    name: String,
    num: u32,
}

#[derive(Clone, Debug, ForeignValue, StructValue)]
struct Bar {
    name: String,
    num: u32,
}

fn interp() -> Interpreter {
    let interp = Interpreter::new();

    interp.scope().register_struct_value::<Foo>();
    interp.scope().register_struct_value::<Bar>();

    interp
}

fn eval(interp: &Interpreter, code: &str) -> Result<Value, Error> {
    interp.run_code(code, None)
}

fn conv<T: FromValue>(interp: &Interpreter, code: &str) -> Result<T, Error> {
    let v = eval(interp, code)?;
    let t = T::from_value(v)?;
    Ok(t)
}

#[test]
fn test_struct() {
    let interp = interp();

    eval(&interp, r#"(define foo (new Foo :name "foo" :num 123))"#).unwrap();

    assert_eq!(conv::<String>(&interp, "(. foo :name)").unwrap(), "foo");
    assert_eq!(conv::<u32>(&interp, "(. foo :num)").unwrap(), 123);

    assert_matches!(eval(&interp, "(. foo :lolwut)").unwrap_err(),
        Error::ExecError(ExecError::FieldError{..}));

    eval(&interp, r#"(define bar (.= foo :name "bar"))"#).unwrap();

    assert_eq!(conv::<String>(&interp, "(. bar :name)").unwrap(), "bar");
    assert_eq!(conv::<u32>(&interp, "(. bar :num)").unwrap(), 123);

    assert_eq!(conv::<bool>(&interp, "(is-instance Foo foo)").unwrap(), true);
    assert_eq!(conv::<bool>(&interp, "(is-instance Bar foo)").unwrap(), false);
}