From 88fec57394d38236d2a87573f6b4c37444f9ce87 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 6 May 2020 16:09:44 +0800 Subject: [PATCH] Make module_resolver optional and remove NullModuleResolver. --- Cargo.toml | 2 +- README.md | 9 +- examples/repl.rs | 3 +- src/engine.rs | 41 +++---- src/module.rs | 305 +++++++++++++++++++++++++---------------------- src/parser.rs | 31 ++--- src/token.rs | 12 -- tests/modules.rs | 4 +- 8 files changed, 200 insertions(+), 207 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2afe38b0..5cf15e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ categories = [ "no-std", "embedded", "parser-implementations" ] num-traits = { version = "0.2.11", default-features = false } [features] -#default = ["no_stdlib", "no_function", "no_index", "no_object", "no_float", "only_i32", "unchecked", "no_optimize", "sync"] +#default = ["no_stdlib", "no_function", "no_index", "no_object", "no_module", "no_float", "only_i32", "unchecked", "no_optimize", "sync"] default = [] unchecked = [] # unchecked arithmetic no_index = [] # no arrays and indexing diff --git a/README.md b/README.md index d8c70be3..e27bf079 100644 --- a/README.md +++ b/README.md @@ -2118,13 +2118,16 @@ Built-in module resolvers are grouped under the `rhai::module_resolvers` module | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `FileModuleResolver` | The default module resolution service, not available under the [`no_std`] feature. Loads a script file (based off the current directory) with `.rhai` extension.
The base directory can be changed via the `FileModuleResolver::new_with_path()` constructor function. | | `StaticModuleResolver` | Loads modules that are statically added. This can be used when the [`no_std`] feature is turned on. | -| `NullModuleResolver` | The default module resolution service under the [`no_std`] feature. Always returns an `EvalAltResult::ErrorModuleNotFound` error. | An [`Engine`]'s module resolver is set via a call to `set_module_resolver`: ```rust -// Use the 'NullModuleResolver' -engine.set_module_resolver(rhai::module_resolvers::NullModuleResolver::new()); +// Use the 'StaticModuleResolver' +let resolver = rhai::module_resolvers::StaticModuleResolver::new(); +engine.set_module_resolver(Some(resolver)); + +// Effectively disable 'import' statements by setting module resolver to 'None' +engine.set_module_resolver(None); ``` Script optimization diff --git a/examples/repl.rs b/examples/repl.rs index af26d593..a8763e28 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -1,4 +1,4 @@ -use rhai::{Dynamic, Engine, EvalAltResult, Map, Scope, AST, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, Scope, AST, INT}; #[cfg(not(feature = "no_optimize"))] use rhai::OptimizationLevel; @@ -163,6 +163,7 @@ fn main() { } // Throw away all the statements, leaving only the functions + #[cfg(not(feature = "no_function"))] main_ast.retain_functions(); } } diff --git a/src/engine.rs b/src/engine.rs index a7beada9..e9e14e1a 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -262,7 +262,7 @@ pub struct Engine { pub(crate) type_iterators: HashMap>, /// A module resolution service. - pub(crate) module_resolver: Box, + pub(crate) module_resolver: Option>, /// A hashmap mapping type names to pretty-print names. pub(crate) type_names: HashMap, @@ -300,9 +300,9 @@ impl Default for Engine { #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_std"))] - module_resolver: Box::new(resolvers::FileModuleResolver::new()), + module_resolver: Some(Box::new(resolvers::FileModuleResolver::new())), #[cfg(any(feature = "no_std", feature = "no_module"))] - module_resolver: Box::new(resolvers::NullModuleResolver::new()), + module_resolver: None, type_names: Default::default(), @@ -438,13 +438,7 @@ impl Engine { packages: Default::default(), functions: HashMap::with_capacity(FUNCTIONS_COUNT / 2), type_iterators: Default::default(), - - #[cfg(not(feature = "no_module"))] - #[cfg(not(feature = "no_std"))] - module_resolver: Box::new(resolvers::FileModuleResolver::new()), - #[cfg(any(feature = "no_std", feature = "no_module"))] - module_resolver: Box::new(resolvers::NullModuleResolver::new()), - + module_resolver: None, type_names: Default::default(), print: Box::new(|_| {}), debug: Box::new(|_| {}), @@ -491,8 +485,8 @@ impl Engine { /// /// Not available under the `no_module` feature. #[cfg(not(feature = "no_module"))] - pub fn set_module_resolver(&mut self, resolver: impl ModuleResolver + 'static) { - self.module_resolver = Box::new(resolver); + pub fn set_module_resolver(&mut self, resolver: Option) { + self.module_resolver = resolver.map(|f| Box::new(f) as Box); } /// Universal method for calling functions either registered with the `Engine` or written in Rhai. @@ -1264,8 +1258,7 @@ impl Engine { let hash = calc_fn_hash(fn_name, args.iter().map(|a| a.type_id())); match module.get_qualified_fn(fn_name, hash, modules, *pos) { - Ok(func) => func(&mut args, *pos) - .map_err(|err| EvalAltResult::set_position(err, *pos)), + Ok(func) => func(&mut args, *pos), Err(_) if def_val.is_some() => Ok(def_val.as_deref().unwrap().clone()), Err(err) => Err(err), } @@ -1530,15 +1523,19 @@ impl Engine { .eval_expr(scope, state, fn_lib, expr, level)? .try_cast::() { - let module = self - .module_resolver - .resolve(self, &path) - .map_err(|err| EvalAltResult::set_position(err, expr.position()))?; + if let Some(resolver) = self.module_resolver.as_ref() { + let module = resolver.resolve(self, &path, expr.position())?; - // TODO - avoid copying module name in inner block? - let mod_name = name.as_ref().clone(); - scope.push_module(mod_name, module); - Ok(Default::default()) + // TODO - avoid copying module name in inner block? + let mod_name = name.as_ref().clone(); + scope.push_module(mod_name, module); + Ok(Default::default()) + } else { + Err(Box::new(EvalAltResult::ErrorModuleNotFound( + path, + expr.position(), + ))) + } } else { Err(Box::new(EvalAltResult::ErrorImportExpr(expr.position()))) } diff --git a/src/module.rs b/src/module.rs index 32d27395..0c329f27 100644 --- a/src/module.rs +++ b/src/module.rs @@ -5,21 +5,35 @@ use crate::calc_fn_hash; use crate::engine::{Engine, FnAny, FnCallArgs, FunctionsLib}; use crate::parser::FnDef; use crate::result::EvalAltResult; -use crate::scope::{EntryType as ScopeEntryType, Scope}; +use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope}; use crate::token::Position; use crate::token::Token; use crate::utils::StaticVec; use crate::stdlib::{ - any::TypeId, collections::HashMap, fmt, iter::empty, mem, rc::Rc, string::String, sync::Arc, + any::TypeId, + collections::HashMap, + fmt, mem, + ops::{Deref, DerefMut}, + rc::Rc, + string::String, + sync::Arc, }; /// A trait that encapsulates a module resolution service. pub trait ModuleResolver { /// Resolve a module based on a path string. - fn resolve(&self, engine: &Engine, path: &str) -> Result>; + fn resolve( + &self, + engine: &Engine, + path: &str, + pos: Position, + ) -> Result>; } +/// Return type of module-level Rust function. +type FuncReturn = Result>; + /// An imported module, which may contain variables, sub-modules, /// external Rust functions, and script-defined functions. /// @@ -158,7 +172,6 @@ impl Module { #[cfg(not(feature = "sync"))] self.functions.insert(hash, Rc::new(func)); - #[cfg(feature = "sync")] self.functions.insert(hash, Arc::new(func)); @@ -171,14 +184,16 @@ impl Module { pub fn set_fn_0>( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn() -> Result> + 'static, - #[cfg(feature = "sync")] func: impl Fn() -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn() -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn() -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |_: &mut FnCallArgs, _: Position| func().map(|v| v.into()); - self.set_fn(fn_name, &[], Box::new(f)) + let f = move |_: &mut FnCallArgs, pos| { + func() + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) + }; + let arg_types = &[]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking one parameter into the module, returning a hash key. @@ -187,16 +202,16 @@ impl Module { pub fn set_fn_1>( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(A) -> Result> + 'static, - #[cfg(feature = "sync")] func: impl Fn(A) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(A) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(A) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { - func(mem::take(args[0]).cast::()).map(|v| v.into()) + let f = move |args: &mut FnCallArgs, pos| { + func(mem::take(args[0]).cast::()) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn(fn_name, &[TypeId::of::()], Box::new(f)) + let arg_types = &[TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking one mutable parameter into the module, returning a hash key. @@ -205,16 +220,16 @@ impl Module { pub fn set_fn_1_mut>( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(&mut A) -> Result> + 'static, - #[cfg(feature = "sync")] func: impl Fn(&mut A) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(&mut A) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(&mut A) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { - func(args[0].downcast_mut::().unwrap()).map(|v| v.into()) + let f = move |args: &mut FnCallArgs, pos| { + func(args[0].downcast_mut::().unwrap()) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn(fn_name, &[TypeId::of::()], Box::new(f)) + let arg_types = &[TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking two parameters into the module, returning a hash key. @@ -223,23 +238,19 @@ impl Module { pub fn set_fn_2>( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> Result> + 'static, - #[cfg(feature = "sync")] func: impl Fn(A, B) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(A, B) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { + let f = move |args: &mut FnCallArgs, pos| { let a = mem::take(args[0]).cast::(); let b = mem::take(args[1]).cast::(); - func(a, b).map(|v| v.into()) + func(a, b) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn( - fn_name, - &[TypeId::of::(), TypeId::of::()], - Box::new(f), - ) + let arg_types = &[TypeId::of::(), TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking two parameters (the first one mutable) into the module, @@ -249,24 +260,19 @@ impl Module { pub fn set_fn_2_mut>( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> Result> - + 'static, - #[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { + let f = move |args: &mut FnCallArgs, pos| { let b = mem::take(args[1]).cast::(); let a = args[0].downcast_mut::().unwrap(); - func(a, b).map(|v| v.into()) + func(a, b) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn( - fn_name, - &[TypeId::of::(), TypeId::of::()], - Box::new(f), - ) + let arg_types = &[TypeId::of::(), TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking three parameters into the module, returning a hash key. @@ -280,24 +286,20 @@ impl Module { >( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> Result> + 'static, - #[cfg(feature = "sync")] func: impl Fn(A, B, C) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(A, B, C) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { + let f = move |args: &mut FnCallArgs, pos| { let a = mem::take(args[0]).cast::(); let b = mem::take(args[1]).cast::(); let c = mem::take(args[2]).cast::(); - func(a, b, c).map(|v| v.into()) + func(a, b, c) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn( - fn_name, - &[TypeId::of::(), TypeId::of::(), TypeId::of::()], - Box::new(f), - ) + let arg_types = &[TypeId::of::(), TypeId::of::(), TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Set a Rust function taking three parameters (the first one mutable) into the module, @@ -312,25 +314,20 @@ impl Module { >( &mut self, fn_name: &str, - #[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> Result> - + 'static, - #[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> Result> - + Send - + Sync - + 'static, + #[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> FuncReturn + 'static, + #[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> FuncReturn + Send + Sync + 'static, ) -> u64 { - let f = move |args: &mut FnCallArgs, _: Position| { + let f = move |args: &mut FnCallArgs, pos| { let b = mem::take(args[1]).cast::(); let c = mem::take(args[2]).cast::(); let a = args[0].downcast_mut::().unwrap(); - func(a, b, c).map(|v| v.into()) + func(a, b, c) + .map(|v| v.into()) + .map_err(|err| EvalAltResult::set_position(err, pos)) }; - self.set_fn( - fn_name, - &[TypeId::of::(), TypeId::of::(), TypeId::of::()], - Box::new(f), - ) + let arg_types = &[TypeId::of::(), TypeId::of::(), TypeId::of::()]; + self.set_fn(fn_name, arg_types, Box::new(f)) } /// Get a Rust function. @@ -388,22 +385,40 @@ impl Module { } } +/// Re-export module resolvers. pub mod resolvers { - use super::*; + pub use super::file::FileModuleResolver; + pub use super::stat::StaticModuleResolver; +} - #[cfg(not(feature = "no_std"))] +/// Script file-based module resolver. +#[cfg(not(feature = "no_std"))] +mod file { + use super::*; use crate::stdlib::path::PathBuf; - /// A module resolution service that loads module script files (assumed `.rhai` extension). - #[cfg(not(feature = "no_std"))] - #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] - pub struct FileModuleResolver(PathBuf); + /// A module resolution service that loads module script files from the file system. + /// + /// The `new_with_path` and `new_with_path_and_extension` constructor functions + /// allow specification of a base directory with module path used as a relative path offset + /// to the base directory. The script file is then forced to be in a specified extension + /// (default `.rhai`). + #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] + pub struct FileModuleResolver { + path: PathBuf, + extension: String, + } - #[cfg(not(feature = "no_std"))] impl FileModuleResolver { /// Create a new `FileModuleResolver` with a specific base path. pub fn new_with_path(path: PathBuf) -> Self { - Self(path) + Self::new_with_path_and_extension(path, "rhai".to_string()) + } + /// Create a new `FileModuleResolver` with a specific base path and file extension. + /// + /// The default extension is `.rhai`. + pub fn new_with_path_and_extension(path: PathBuf, extension: String) -> Self { + Self { path, extension } } /// Create a new `FileModuleResolver` with the current directory as base path. pub fn new() -> Self { @@ -411,54 +426,63 @@ pub mod resolvers { } } - #[cfg(not(feature = "no_std"))] - impl Default for FileModuleResolver { - fn default() -> Self { - Self::new_with_path(".".into()) - } - } - - #[cfg(not(feature = "no_std"))] impl ModuleResolver for FileModuleResolver { - fn resolve(&self, engine: &Engine, path: &str) -> Result> { - // Load the script file (attaching `.rhai`) - let mut file_path = self.0.clone(); + fn resolve( + &self, + engine: &Engine, + path: &str, + pos: Position, + ) -> Result> { + // Construct the script file path + let mut file_path = self.path.clone(); file_path.push(path); - file_path.set_extension("rhai"); + file_path.set_extension(&self.extension); // Force extension // Compile it - let ast = engine.compile_file(file_path)?; + let ast = engine + .compile_file(file_path) + .map_err(|err| EvalAltResult::set_position(err, pos))?; // Use new scope let mut scope = Scope::new(); // Run the script - engine.eval_ast_with_scope_raw(&mut scope, &ast)?; + engine + .eval_ast_with_scope_raw(&mut scope, &ast) + .map_err(|err| EvalAltResult::set_position(err, pos))?; // Create new module let mut module = Module::new(); - // Variables left in the scope become module variables - for entry in scope.into_iter() { - match entry.typ { - ScopeEntryType::Normal | ScopeEntryType::Constant => { - module - .variables - .insert(entry.name.into_owned(), entry.value); + scope.into_iter().for_each( + |ScopeEntry { + name, typ, value, .. + }| { + match typ { + // Variables left in the scope become module variables + ScopeEntryType::Normal | ScopeEntryType::Constant => { + module.variables.insert(name.into_owned(), value); + } + // Modules left in the scope become sub-modules + ScopeEntryType::Module => { + module + .modules + .insert(name.into_owned(), value.cast::()); + } } - ScopeEntryType::Module => { - module - .modules - .insert(entry.name.into_owned(), entry.value.cast::()); - } - } - } + }, + ); - module.fn_lib = FunctionsLib::new().merge(ast.fn_lib()); + module.fn_lib = module.fn_lib.merge(ast.fn_lib()); Ok(module) } } +} + +/// Static module resolver. +mod stat { + use super::*; /// A module resolution service that serves modules added into it. #[derive(Debug, Clone, Default)] @@ -469,40 +493,33 @@ pub mod resolvers { pub fn new() -> Self { Default::default() } - /// Add a named module. - pub fn add_module(&mut self, name: &str, module: Module) { - self.0.insert(name.to_string(), module); + } + + impl Deref for StaticModuleResolver { + type Target = HashMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl DerefMut for StaticModuleResolver { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 } } impl ModuleResolver for StaticModuleResolver { - fn resolve(&self, _: &Engine, path: &str) -> Result> { - self.0.get(path).cloned().ok_or_else(|| { - Box::new(EvalAltResult::ErrorModuleNotFound( - path.to_string(), - Position::none(), - )) - }) - } - } - - /// A module resolution service that always returns a not-found error. - #[derive(Debug, Clone, PartialEq, Eq, Copy, Default)] - pub struct NullModuleResolver; - - impl NullModuleResolver { - /// Create a new `NullModuleResolver`. - pub fn new() -> Self { - Default::default() - } - } - - impl ModuleResolver for NullModuleResolver { - fn resolve(&self, _: &Engine, path: &str) -> Result> { - Err(Box::new(EvalAltResult::ErrorModuleNotFound( - path.to_string(), - Position::none(), - ))) + fn resolve( + &self, + _: &Engine, + path: &str, + pos: Position, + ) -> Result> { + self.0 + .get(path) + .cloned() + .ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(path.to_string(), pos))) } } } diff --git a/src/parser.rs b/src/parser.rs index 4cb663d8..b1e91eb0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -67,13 +67,9 @@ impl AST { /// Create a new `AST`. pub fn new(statements: Vec, fn_lib: FunctionsLib) -> Self { #[cfg(feature = "sync")] - { - Self(statements, Arc::new(fn_lib)) - } + return Self(statements, Arc::new(fn_lib)); #[cfg(not(feature = "sync"))] - { - Self(statements, Rc::new(fn_lib)) - } + return Self(statements, Rc::new(fn_lib)); } /// Get the statements. @@ -148,13 +144,9 @@ impl AST { }; #[cfg(feature = "sync")] - { - Self(ast, Arc::new(functions.merge(other.1.as_ref()))) - } + return Self(ast, Arc::new(functions.merge(other.1.as_ref()))); #[cfg(not(feature = "sync"))] - { - Self(ast, Rc::new(functions.merge(other.1.as_ref()))) - } + return Self(ast, Rc::new(functions.merge(other.1.as_ref()))); } /// Clear all function definitions in the `AST`. @@ -1810,7 +1802,6 @@ fn parse_let<'a>( } /// Parse an import statement. -#[cfg(not(feature = "no_module"))] fn parse_import<'a>( input: &mut Peekable>, stack: &mut Stack, @@ -1941,7 +1932,6 @@ fn parse_stmt<'a>( Token::LeftBrace => parse_block(input, stack, breakable, allow_stmt_expr), // fn ... - #[cfg(not(feature = "no_function"))] Token::Fn => Err(PERR::WrongFnDefinition.into_err(*pos)), Token::If => parse_if(input, stack, breakable, allow_stmt_expr), @@ -2115,14 +2105,11 @@ fn parse_global_level<'a>( while !input.peek().unwrap().0.is_eof() { // Collect all the function definitions - #[cfg(not(feature = "no_function"))] - { - if let (Token::Fn, _) = input.peek().unwrap() { - let mut stack = Stack::new(); - let f = parse_fn(input, &mut stack, true)?; - functions.insert(calc_fn_def(&f.name, f.params.len()), f); - continue; - } + if let (Token::Fn, _) = input.peek().unwrap() { + let mut stack = Stack::new(); + let f = parse_fn(input, &mut stack, true)?; + functions.insert(calc_fn_def(&f.name, f.params.len()), f); + continue; } // Actual statement diff --git a/src/token.rs b/src/token.rs index 29e7ce87..f67a8e14 100644 --- a/src/token.rs +++ b/src/token.rs @@ -153,11 +153,9 @@ pub enum Token { RightShift, SemiColon, Colon, - #[cfg(not(feature = "no_module"))] DoubleColon, Comma, Period, - #[cfg(not(feature = "no_object"))] MapStart, Equals, True, @@ -182,7 +180,6 @@ pub enum Token { XOr, Ampersand, And, - #[cfg(not(feature = "no_function"))] Fn, Continue, Break, @@ -199,11 +196,8 @@ pub enum Token { XOrAssign, ModuloAssign, PowerOfAssign, - #[cfg(not(feature = "no_module"))] Import, - #[cfg(not(feature = "no_module"))] Export, - #[cfg(not(feature = "no_module"))] As, LexError(Box), EOF, @@ -238,11 +232,9 @@ impl Token { Divide => "/", SemiColon => ";", Colon => ":", - #[cfg(not(feature = "no_module"))] DoubleColon => "::", Comma => ",", Period => ".", - #[cfg(not(feature = "no_object"))] MapStart => "#{", Equals => "=", True => "true", @@ -266,7 +258,6 @@ impl Token { Or => "||", Ampersand => "&", And => "&&", - #[cfg(not(feature = "no_function"))] Fn => "fn", Continue => "continue", Break => "break", @@ -288,11 +279,8 @@ impl Token { ModuloAssign => "%=", PowerOf => "~", PowerOfAssign => "~=", - #[cfg(not(feature = "no_module"))] Import => "import", - #[cfg(not(feature = "no_module"))] Export => "export", - #[cfg(not(feature = "no_module"))] As => "as", EOF => "{EOF}", _ => panic!("operator should be match in outer scope"), diff --git a/tests/modules.rs b/tests/modules.rs index e1382764..e6028179 100644 --- a/tests/modules.rs +++ b/tests/modules.rs @@ -64,10 +64,10 @@ fn test_module_resolver() -> Result<(), Box> { let mut module = Module::new(); module.set_var("answer", 42 as INT); - resolver.add_module("hello", module); + resolver.insert("hello".to_string(), module); let mut engine = Engine::new(); - engine.set_module_resolver(resolver); + engine.set_module_resolver(Some(resolver)); assert_eq!( engine.eval::(