Add more module tests.
This commit is contained in:
parent
e8d5f78f88
commit
d2c94ba07c
87
benches/eval_module.rs
Normal file
87
benches/eval_module.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
///! Test evaluating with scope
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
use rhai::{module_resolvers::StaticModuleResolver, Engine, Module, OptimizationLevel};
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_eval_module_merged(bench: &mut Bencher) {
|
||||||
|
let script = r#"
|
||||||
|
fn foo(x) { x + 1 }
|
||||||
|
fn bar(x) { foo(x) }
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
engine.set_optimization_level(OptimizationLevel::None);
|
||||||
|
|
||||||
|
let ast = engine.compile(script).unwrap();
|
||||||
|
|
||||||
|
let module = Module::eval_ast_as_new(Default::default(), &ast, true, &engine).unwrap();
|
||||||
|
|
||||||
|
let mut resolver = StaticModuleResolver::new();
|
||||||
|
resolver.insert("testing", module);
|
||||||
|
engine.set_module_resolver(Some(resolver));
|
||||||
|
|
||||||
|
let ast = engine
|
||||||
|
.compile(
|
||||||
|
r#"
|
||||||
|
fn foo(x) { x - 1 }
|
||||||
|
import "testing" as t;
|
||||||
|
t::bar(41)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_eval_module_unmerged(bench: &mut Bencher) {
|
||||||
|
let script = r#"
|
||||||
|
fn foo(x) { x + 1 }
|
||||||
|
fn bar(x) { foo(x) }
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
engine.set_optimization_level(OptimizationLevel::None);
|
||||||
|
|
||||||
|
let ast = engine.compile(script).unwrap();
|
||||||
|
|
||||||
|
let module = Module::eval_ast_as_new(Default::default(), &ast, false, &engine).unwrap();
|
||||||
|
|
||||||
|
let mut resolver = StaticModuleResolver::new();
|
||||||
|
resolver.insert("testing", module);
|
||||||
|
engine.set_module_resolver(Some(resolver));
|
||||||
|
|
||||||
|
let ast = engine
|
||||||
|
.compile(
|
||||||
|
r#"
|
||||||
|
fn foo(x) { x - 1 }
|
||||||
|
import "testing" as t;
|
||||||
|
t::bar(41)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_eval_function_call(bench: &mut Bencher) {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
engine.set_optimization_level(OptimizationLevel::None);
|
||||||
|
|
||||||
|
let ast = engine
|
||||||
|
.compile(
|
||||||
|
r#"
|
||||||
|
fn foo(x) { x - 1 }
|
||||||
|
fn bar(x) { foo(x) }
|
||||||
|
bar(41)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
||||||
|
}
|
@ -27,9 +27,13 @@ functions exposed by the module and the namespace that they can access:
|
|||||||
|
|
||||||
| `merge_namespaces` value | Description | Namespace | Performance | Call global functions | Call functions in same module |
|
| `merge_namespaces` value | Description | Namespace | Performance | Call global functions | Call functions in same module |
|
||||||
| :----------------------: | ------------------------------------------------ | :-----------------: | :---------: | :-------------------: | :---------------------------: |
|
| :----------------------: | ------------------------------------------------ | :-----------------: | :---------: | :-------------------: | :---------------------------: |
|
||||||
| `true` | encapsulate entire `AST` into each function call | module, then global | slower | yes | yes |
|
| `true` | encapsulate entire `AST` into each function call | module, then global | 2x slower | yes | yes |
|
||||||
| `false` | register each function independently | global only | fast | yes | no |
|
| `false` | register each function independently | global only | fast | yes | no |
|
||||||
|
|
||||||
|
If the ultimate intention is to load the [module] directly into an [`Engine`] via `Engine::load_package`,
|
||||||
|
set `merge_namespaces` to `false` because there will not be any _module_ namespace as `Engine::load_package`
|
||||||
|
flattens everything into the _global_ namespace anyway.
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
@ -78,7 +82,9 @@ let ast = engine.compile(r#"
|
|||||||
// a copy of the entire 'AST' into each function, allowing functions in the module script
|
// a copy of the entire 'AST' into each function, allowing functions in the module script
|
||||||
// to cross-call each other.
|
// to cross-call each other.
|
||||||
//
|
//
|
||||||
// This incurs additional overhead, avoidable by setting 'merge_namespaces' to false.
|
// This incurs additional overhead, avoidable by setting 'merge_namespaces' to false
|
||||||
|
// which makes function calls 2x faster but at the expense of not being able to cross-call
|
||||||
|
// functions in the same module script.
|
||||||
let module = Module::eval_ast_as_new(Scope::new(), &ast, true, &engine)?;
|
let module = Module::eval_ast_as_new(Scope::new(), &ast, true, &engine)?;
|
||||||
|
|
||||||
// 'module' now contains:
|
// 'module' now contains:
|
||||||
|
@ -178,7 +178,7 @@ macro_rules! def_register {
|
|||||||
(imp $abi:ident : $($par:ident => $arg:expr => $mark:ty => $param:ty => $let:stmt => $clone:expr),*) => {
|
(imp $abi:ident : $($par:ident => $arg:expr => $mark:ty => $param:ty => $let:stmt => $clone:expr),*) => {
|
||||||
// ^ function ABI type
|
// ^ function ABI type
|
||||||
// ^ function parameter generic type name (A, B, C etc.)
|
// ^ function parameter generic type name (A, B, C etc.)
|
||||||
// ^ call argument(like A, *B, &mut C etc)
|
// ^ call argument(like A, *B, &mut C etc)
|
||||||
// ^ function parameter marker type (T, Ref<T> or Mut<T>)
|
// ^ function parameter marker type (T, Ref<T> or Mut<T>)
|
||||||
// ^ function parameter actual type (T, &T or &mut T)
|
// ^ function parameter actual type (T, &T or &mut T)
|
||||||
// ^ argument let statement
|
// ^ argument let statement
|
||||||
|
@ -1260,8 +1260,12 @@ impl Module {
|
|||||||
/// defined in the module, are _merged_ into a _unified_ namespace before each call.
|
/// defined in the module, are _merged_ into a _unified_ namespace before each call.
|
||||||
/// Therefore, all functions will be found, at the expense of some performance.
|
/// Therefore, all functions will be found, at the expense of some performance.
|
||||||
///
|
///
|
||||||
/// * If `false`, each function is registered independently and cannot cross-call
|
/// * If `false`, each function is registered independently and cannot cross-call each other.
|
||||||
/// each other. Functions are searched in the global namespace.
|
/// Functions are searched in the global namespace.
|
||||||
|
/// This is roughly 2x faster than the `true` case.
|
||||||
|
///
|
||||||
|
/// Set `merge_namespaces` to `false` if the ultimate intention is to load the module
|
||||||
|
/// via `Engine::load_package` because it does not create any module namespace.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -361,3 +361,40 @@ fn test_module_str() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_module_ast_namespace() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let script = r#"
|
||||||
|
fn foo(x) { x + 1 }
|
||||||
|
fn bar(x) { foo(x) }
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
let ast = engine.compile(script)?;
|
||||||
|
|
||||||
|
let module = Module::eval_ast_as_new(Default::default(), &ast, true, &engine)?;
|
||||||
|
|
||||||
|
let mut resolver = StaticModuleResolver::new();
|
||||||
|
resolver.insert("testing", module);
|
||||||
|
engine.set_module_resolver(Some(resolver));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(r#"import "testing" as t; t::foo(41)"#)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(r#"import "testing" as t; t::bar(41)"#)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(r#"fn foo(x) { x - 1 } import "testing" as t; t::foo(41)"#)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(r#"fn foo(x) { x - 1 } import "testing" as t; t::bar(41)"#)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user