New Procedural Macros Crate v0.1

This commit is contained in:
J Henry Waugh
2020-08-01 11:52:26 -05:00
parent 99d56b8f81
commit d01203cb5d
28 changed files with 2230 additions and 5 deletions

View File

@@ -0,0 +1,141 @@
use rhai::{EvalAltResult, FLOAT, INT, Module, RegisterFn};
use rhai::plugin::*;
use rhai::module_resolvers::*;
pub mod raw_fn {
use rhai::FLOAT;
use rhai::export_fn;
#[export_fn]
pub fn distance_function(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt()
}
}
#[test]
fn raw_fn_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || { 42 as FLOAT });
let mut m = Module::new();
rhai::register_exported_fn!(m, "euclidean_distance".to_string(), raw_fn::distance_function);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let x = math::euclidean_distance(0.0, 1.0, 0.0, get_mystic_number()); x"#)?, 41.0);
Ok(())
}
mod raw_fn_mut {
use rhai::FLOAT;
use rhai::export_fn;
#[export_fn]
pub fn add_in_place(f1: &mut FLOAT, f2: FLOAT) {
*f1 += f2;
}
}
#[test]
fn raw_fn_mut_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || { 42 as FLOAT });
let mut m = Module::new();
rhai::register_exported_fn!(m, "add_in_place", raw_fn_mut::add_in_place);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let x = get_mystic_number();
math::add_in_place(x, 1.0);
x"#)?, 43.0);
Ok(())
}
mod raw_fn_str {
use rhai::export_fn;
#[export_fn]
pub fn write_out_str(message: &str) -> bool {
eprintln!("{}", message);
true
}
}
#[test]
fn raw_fn_str_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.register_fn("get_mystic_number", || { 42 as FLOAT });
let mut m = Module::new();
rhai::register_exported_fn!(m, "write_out_str", raw_fn_str::write_out_str);
let mut r = StaticModuleResolver::new();
r.insert("Host::IO".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<bool>(
r#"import "Host::IO" as io;
let x = io::write_out_str("hello world!");
x"#)?, true);
Ok(())
}
mod mut_opaque_ref {
use rhai::INT;
use rhai::export_fn;
#[derive(Clone)]
pub struct StatusMessage {
os_code: Option<INT>,
message: String,
is_ok: bool
}
#[export_fn]
pub fn new_message(is_ok: bool, message: &str) -> StatusMessage {
StatusMessage {
is_ok,
os_code: None,
message: message.to_string(),
}
}
#[export_fn]
pub fn new_os_message(is_ok: bool, os_code: INT) -> StatusMessage {
StatusMessage {
is_ok,
os_code: Some(os_code),
message: format!("OS Code {}", os_code),
}
}
#[export_fn]
pub fn write_out_message(message: &mut StatusMessage) -> bool {
eprintln!("{}", message.message);
true
}
}
#[test]
fn mut_opaque_ref_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let mut m = Module::new();
rhai::register_exported_fn!(m, "new_message", mut_opaque_ref::new_message);
rhai::register_exported_fn!(m, "new_os_message", mut_opaque_ref::new_os_message);
rhai::register_exported_fn!(m, "write_out_message", mut_opaque_ref::write_out_message);
let mut r = StaticModuleResolver::new();
r.insert("Host::Msg".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<bool>(
r#"import "Host::Msg" as msg;
let message1 = msg::new_message(true, "it worked");
let ok1 = msg::write_out_message(message1);
let message2 = msg::new_os_message(true, 0);
let ok2 = msg::write_out_message(message2);
ok1 && ok2"#)?, true);
Ok(())
}

View File

@@ -0,0 +1,165 @@
use rhai::{EvalAltResult, FLOAT, INT, RegisterFn};
use rhai::plugin::*;
use rhai::module_resolvers::*;
pub mod empty_module {
use rhai::export_module;
#[export_module]
pub mod EmptyModule { }
}
#[test]
fn empty_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::empty_module::EmptyModule);
let mut r = StaticModuleResolver::new();
r.insert("Module::Empty".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<INT>(
r#"import "Module::Empty" as m; 42"#)?, 42);
Ok(())
}
pub mod one_fn_module {
use rhai::export_module;
#[export_module]
pub mod advanced_math {
use rhai::FLOAT;
pub fn get_mystic_number() -> FLOAT {
42.0 as FLOAT
}
}
}
#[test]
fn one_fn_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_module::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::get_mystic_number();
m"#)?, 42.0);
Ok(())
}
pub mod one_fn_and_const_module {
use rhai::export_module;
#[export_module]
pub mod advanced_math {
use rhai::FLOAT;
pub const MYSTIC_NUMBER: FLOAT = 42.0 as FLOAT;
pub fn euclidean_distance(x1: FLOAT, y1: FLOAT, x2: FLOAT, y2: FLOAT) -> FLOAT {
((y2 - y1).abs().powf(2.0) + (x2 -x1).abs().powf(2.0)).sqrt()
}
}
}
#[test]
fn one_fn_and_const_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::one_fn_and_const_module::advanced_math);
let mut r = StaticModuleResolver::new();
r.insert("Math::Advanced".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<FLOAT>(
r#"import "Math::Advanced" as math;
let m = math::MYSTIC_NUMBER;
let x = math::euclidean_distance(0.0, 1.0, 0.0, m);
x"#)?, 41.0);
Ok(())
}
pub mod raw_fn_str_module {
use rhai::export_module;
#[export_module]
pub mod host_io {
pub fn write_out_str(message: &str) -> bool {
eprintln!("{}", message);
true
}
}
}
#[test]
fn raw_fn_str_module_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::raw_fn_str_module::host_io);
let mut r = StaticModuleResolver::new();
r.insert("Host::IO".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<bool>(
r#"import "Host::IO" as io;
let x = io::write_out_str("hello world!");
x"#)?, true);
Ok(())
}
pub mod mut_opaque_ref_module {
use rhai::INT;
use rhai::export_module;
#[derive(Clone)]
pub struct StatusMessage {
os_code: Option<INT>,
message: String,
is_ok: bool
}
#[export_module]
pub mod host_msg {
use super::{INT, StatusMessage};
pub fn new_message(is_ok: bool, message: &str) -> StatusMessage {
StatusMessage {
is_ok,
os_code: None,
message: message.to_string(),
}
}
pub fn new_os_message(is_ok: bool, os_code: INT) -> StatusMessage {
StatusMessage {
is_ok,
os_code: Some(os_code),
message: format!("OS Code {}", os_code),
}
}
pub fn write_out_message(message: &mut StatusMessage) -> bool {
eprintln!("{}", message.message);
true
}
}
}
#[test]
fn mut_opaque_ref_test() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
let m = rhai::exported_module!(crate::mut_opaque_ref_module::host_msg);
let mut r = StaticModuleResolver::new();
r.insert("Host::Msg".to_string(), m);
engine.set_module_resolver(Some(r));
assert_eq!(engine.eval::<bool>(
r#"import "Host::Msg" as msg;
let success = "it worked";
let message1 = msg::new_message(true, success);
let ok1 = msg::write_out_message(message1);
let message2 = msg::new_os_message(true, 0);
let ok2 = msg::write_out_message(message2);
ok1 && ok2"#)?, true);
Ok(())
}