From 92ba7b42d5b3b34f10e17b9c9c00fe5e5f46fdd0 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 20 Oct 2020 10:54:32 +0800 Subject: [PATCH] Implement namespaces chain. --- doc/src/engine/custom-syntax.md | 2 +- doc/src/engine/var.md | 2 +- doc/src/language/fn-ptr.md | 4 +- doc/src/rust/register-raw.md | 3 +- src/api.rs | 68 ++++++++++---------------- src/engine.rs | 28 +++++------ src/fn_call.rs | 86 ++++++++++++++++++++------------- src/fn_native.rs | 20 ++++---- src/optimize.rs | 13 ++--- src/syntax.rs | 4 +- tests/closures.rs | 2 +- 11 files changed, 119 insertions(+), 113 deletions(-) diff --git a/doc/src/engine/custom-syntax.md b/doc/src/engine/custom-syntax.md index 6bbe1157..e635fcdc 100644 --- a/doc/src/engine/custom-syntax.md +++ b/doc/src/engine/custom-syntax.md @@ -121,7 +121,7 @@ where: * `context: &mut EvalContext` - mutable reference to the current evaluation _context_, exposing the following: * `context.scope: &mut Scope` - mutable reference to the current [`Scope`]; variables can be added to/removed from it. * `context.engine(): &Engine` - reference to the current [`Engine`]. - * `context.namespace(): &Module` - reference to the current _global namespace_ (as a [module]) containing all script-defined functions. + * `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions. * `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any. * `context.call_level(): usize` - the current nesting level of function calls. diff --git a/doc/src/engine/var.md b/doc/src/engine/var.md index 00b6a4fd..46468ae5 100644 --- a/doc/src/engine/var.md +++ b/doc/src/engine/var.md @@ -77,7 +77,7 @@ where: * `context: &EvalContext` - reference to the current evaluation _context_, which exposes the following fields: * `context.scope: &Scope` - reference to the current [`Scope`] containing all variables up to the current evaluation position. * `context.engine(): &Engine` - reference to the current [`Engine`]. - * `context.namespace(): &Module` - reference to the current _global namespace_ (as a [module]) containing all script-defined functions. + * `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions. * `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any. * `context.call_level(): usize` - the current nesting level of function calls. diff --git a/doc/src/language/fn-ptr.md b/doc/src/language/fn-ptr.md index 00e9edac..bb7543a3 100644 --- a/doc/src/language/fn-ptr.md +++ b/doc/src/language/fn-ptr.md @@ -249,8 +249,8 @@ let fn_ptr = engine.eval_ast::(&ast)?; ast.retain_functions(|_, _, _| true); // Create native call context via a tuple containing the Engine and the -// set of script-defined functions (within the AST) -let context = (&engine, ast.as_ref()).into(); +// set of script-defined functions (within the AST) in form of a slice. +let context = (&engine, &[ast.as_ref()]).into(); // 'f' captures: the engine, the AST, and the closure let f = move |x: i64| fn_ptr.call_dynamic(context, None, [x.into()]); diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md index 87854acc..b35212e1 100644 --- a/doc/src/rust/register-raw.md +++ b/doc/src/rust/register-raw.md @@ -72,8 +72,7 @@ where: * `context.engine(): &Engine` - the current [`Engine`], with all configurations and settings. This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. - - * `context.namespace(): &Module` - the global namespace of script-defined functions, as a [`Module`]. + * `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions. * `args: &mut [&mut Dynamic]` - a slice containing `&mut` references to [`Dynamic`] values. The slice is guaranteed to contain enough arguments _of the correct types_. diff --git a/src/api.rs b/src/api.rs index 2e962b4f..cfb1199a 100644 --- a/src/api.rs +++ b/src/api.rs @@ -804,7 +804,7 @@ impl Engine { /// ``` #[inline(always)] pub fn compile(&self, script: &str) -> Result { - self.compile_with_scope(&Scope::new(), script) + self.compile_with_scope(&Default::default(), script) } /// Compile a string into an `AST` using own scope, which can be used later for evaluation. @@ -965,7 +965,7 @@ impl Engine { #[cfg(not(target_arch = "wasm32"))] #[inline(always)] pub fn compile_file(&self, path: PathBuf) -> Result> { - self.compile_file_with_scope(&Scope::new(), path) + self.compile_file_with_scope(&Default::default(), path) } /// Compile a script file into an `AST` using own scope, which can be used later for evaluation. @@ -1050,7 +1050,7 @@ impl Engine { /// ``` #[cfg(not(feature = "no_object"))] pub fn parse_json(&self, json: &str, has_null: bool) -> Result> { - let mut scope = Scope::new(); + let mut scope = Default::default(); // Trims the JSON string and add a '#' in front let json_text = json.trim_start(); @@ -1112,7 +1112,7 @@ impl Engine { /// ``` #[inline(always)] pub fn compile_expression(&self, script: &str) -> Result { - self.compile_expression_with_scope(&Scope::new(), script) + self.compile_expression_with_scope(&Default::default(), script) } /// Compile a string containing an expression into an `AST` using own scope, @@ -1236,7 +1236,7 @@ impl Engine { /// ``` #[inline(always)] pub fn eval(&self, script: &str) -> Result> { - self.eval_with_scope(&mut Scope::new(), script) + self.eval_with_scope(&mut Default::default(), script) } /// Evaluate a string with own scope. @@ -1294,7 +1294,7 @@ impl Engine { &self, script: &str, ) -> Result> { - self.eval_expression_with_scope(&mut Scope::new(), script) + self.eval_expression_with_scope(&mut Default::default(), script) } /// Evaluate a string containing an expression with own scope. @@ -1350,7 +1350,7 @@ impl Engine { /// ``` #[inline(always)] pub fn eval_ast(&self, ast: &AST) -> Result> { - self.eval_ast_with_scope(&mut Scope::new(), ast) + self.eval_ast_with_scope(&mut Default::default(), ast) } /// Evaluate an `AST` with own scope. @@ -1388,7 +1388,7 @@ impl Engine { scope: &mut Scope, ast: &AST, ) -> Result> { - let mut mods = Imports::new(); + let mut mods = Default::default(); let (result, _) = self.eval_ast_with_scope_raw(scope, &mut mods, ast)?; let typ = self.map_type_name(result.type_name()); @@ -1404,26 +1404,14 @@ impl Engine { } /// Evaluate an `AST` with own scope. - #[inline] + #[inline(always)] pub(crate) fn eval_ast_with_scope_raw<'a>( &self, scope: &mut Scope, mods: &mut Imports, ast: &'a AST, ) -> Result<(Dynamic, u64), Box> { - let mut state = State::new(); - - ast.statements() - .iter() - .try_fold(().into(), |_, stmt| { - self.eval_stmt(scope, mods, &mut state, ast.lib(), &mut None, stmt, 0) - }) - .or_else(|err| match *err { - EvalAltResult::Return(out, _) => Ok(out), - EvalAltResult::LoopBreak(_, _) => unreachable!(), - _ => Err(err), - }) - .map(|v| (v, state.operations)) + self.eval_statements(scope, mods, ast.statements(), &[ast.lib()]) } /// Evaluate a file, but throw away the result and only return error (if any). @@ -1452,7 +1440,7 @@ impl Engine { /// Useful for when you don't need the result, but still need to keep track of possible errors. #[inline(always)] pub fn consume(&self, script: &str) -> Result<(), Box> { - self.consume_with_scope(&mut Scope::new(), script) + self.consume_with_scope(&mut Default::default(), script) } /// Evaluate a string with own scope, but throw away the result and only return error (if any). @@ -1473,33 +1461,20 @@ impl Engine { /// Useful for when you don't need the result, but still need to keep track of possible errors. #[inline(always)] pub fn consume_ast(&self, ast: &AST) -> Result<(), Box> { - self.consume_ast_with_scope(&mut Scope::new(), ast) + self.consume_ast_with_scope(&mut Default::default(), ast) } /// Evaluate an `AST` with own scope, but throw away the result and only return error (if any). /// Useful for when you don't need the result, but still need to keep track of possible errors. - #[inline] + #[inline(always)] pub fn consume_ast_with_scope( &self, scope: &mut Scope, ast: &AST, ) -> Result<(), Box> { - let mut state = State::new(); let mut mods = Default::default(); - - ast.statements() - .iter() - .try_fold(().into(), |_, stmt| { - self.eval_stmt(scope, &mut mods, &mut state, ast.lib(), &mut None, stmt, 0) - }) - .map_or_else( - |err| match *err { - EvalAltResult::Return(_, _) => Ok(()), - EvalAltResult::LoopBreak(_, _) => unreachable!(), - _ => Err(err), - }, - |_| Ok(()), - ) + self.eval_statements(scope, &mut mods, ast.statements(), &[ast.lib()]) + .map(|_| ()) } /// Call a script function defined in an `AST` with multiple arguments. @@ -1651,14 +1626,23 @@ impl Engine { .ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::none()))?; let mut state = State::new(); - let mut mods = Imports::new(); + let mut mods = Default::default(); // Check for data race. if cfg!(not(feature = "no_closure")) { ensure_no_data_race(name, args, false)?; } - self.call_script_fn(scope, &mut mods, &mut state, lib, this_ptr, fn_def, args, 0) + self.call_script_fn( + scope, + &mut mods, + &mut state, + &[lib], + this_ptr, + fn_def, + args, + 0, + ) } /// Optimize the `AST` with constants defined in an external Scope. diff --git a/src/engine.rs b/src/engine.rs index 5f1022c5..9d437937 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -441,17 +441,17 @@ pub struct Limits { /// Context of a script evaluation process. #[derive(Debug)] -pub struct EvalContext<'e, 'x, 'px: 'x, 'a, 's, 'm, 't, 'pt: 't> { +pub struct EvalContext<'e, 'x, 'px: 'x, 'a, 's, 'm, 'pm: 'm, 't, 'pt: 't> { engine: &'e Engine, pub scope: &'x mut Scope<'px>, pub(crate) mods: &'a mut Imports, pub(crate) state: &'s mut State, - lib: &'m Module, + lib: &'m [&'pm Module], pub(crate) this_ptr: &'t mut Option<&'pt mut Dynamic>, level: usize, } -impl<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> { +impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> { /// The current `Engine`. #[inline(always)] pub fn engine(&self) -> &'e Engine { @@ -465,9 +465,9 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't, pub fn imports(&self) -> &'a Imports { self.mods } - /// The global namespace containing definition of all script-defined functions. + /// The chain of namespaces containing definition of all script-defined functions. #[inline(always)] - pub fn namespace(&self) -> &'m Module { + pub fn namespaces(&self) -> &'m [&'pm Module] { self.lib } /// The current bound `this` pointer, if any. @@ -757,7 +757,7 @@ impl Engine { scope: &'s mut Scope, mods: &'s mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &'s mut Option<&mut Dynamic>, expr: &'a Expr, ) -> Result<(Target<'s>, &'a str, ScopeEntryType, Position), Box> { @@ -792,7 +792,7 @@ impl Engine { scope: &'s mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &'s mut Option<&mut Dynamic>, expr: &'a Expr, ) -> Result<(Target<'s>, &'a str, ScopeEntryType, Position), Box> { @@ -862,7 +862,7 @@ impl Engine { fn eval_dot_index_chain_helper( &self, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, target: &mut Target, rhs: &Expr, @@ -1155,7 +1155,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, expr: &Expr, level: usize, @@ -1234,7 +1234,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, expr: &Expr, chain_type: ChainType, @@ -1305,7 +1305,7 @@ impl Engine { fn get_indexed_mut<'a>( &self, state: &mut State, - _lib: &Module, + _lib: &[&Module], target: &'a mut Target, idx: Dynamic, idx_pos: Position, @@ -1414,7 +1414,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, lhs: &Expr, rhs: &Expr, @@ -1477,7 +1477,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, expr: &Expr, level: usize, @@ -1786,7 +1786,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, stmt: &Stmt, level: usize, diff --git a/src/fn_call.rs b/src/fn_call.rs index 8e9c1940..f2ed914f 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -10,7 +10,7 @@ use crate::error::ParseErrorType; use crate::fn_native::{FnCallArgs, FnPtr}; use crate::module::{Module, ModuleRef}; use crate::optimize::OptimizationLevel; -use crate::parser::{Expr, ImmutableString, AST, INT}; +use crate::parser::{Expr, ImmutableString, Stmt, INT}; use crate::result::EvalAltResult; use crate::scope::Scope; use crate::stdlib::ops::Deref; @@ -180,7 +180,7 @@ impl Engine { pub(crate) fn call_native_fn( &self, state: &mut State, - lib: &Module, + lib: &[&Module], fn_name: &str, hash_fn: u64, args: &mut FnCallArgs, @@ -345,7 +345,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, fn_def: &ScriptFnDef, args: &mut FnCallArgs, @@ -382,17 +382,15 @@ impl Engine { ); // Merge in encapsulated environment, if any - let mut lib_merged; + let mut lib_merged: StaticVec<_>; let unified_lib = if let Some(ref env_lib) = fn_def.lib { - if lib.is_empty() { - // In the special case of the main script not defining any function - env_lib - } else { - lib_merged = lib.clone(); - lib_merged.merge(env_lib); - &lib_merged + lib_merged = Default::default(); + lib_merged.push(env_lib.as_ref()); + if !lib.is_empty() { + lib_merged.extend(lib.iter().cloned()); } + lib_merged.as_ref() } else { lib }; @@ -433,7 +431,7 @@ impl Engine { #[inline] pub(crate) fn has_override_by_name_and_arguments( &self, - lib: &Module, + lib: &[&Module], name: &str, arg_types: impl AsRef<[TypeId]>, pub_only: bool, @@ -456,7 +454,7 @@ impl Engine { #[inline(always)] pub(crate) fn has_override( &self, - lib: &Module, + lib: &[&Module], hash_fn: u64, hash_script: u64, pub_only: bool, @@ -464,8 +462,8 @@ impl Engine { // NOTE: We skip script functions for global_module and packages, and native functions for lib // First check script-defined functions - lib.contains_fn(hash_script, pub_only) - //|| lib.contains_fn(hash_fn, pub_only) + lib.iter().any(|&m| m.contains_fn(hash_script, pub_only)) + //|| lib.iter().any(|&m| m.contains_fn(hash_fn, pub_only)) // Then check registered functions //|| self.global_module.contains_fn(hash_script, pub_only) || self.global_module.contains_fn(hash_fn, pub_only) @@ -485,7 +483,7 @@ impl Engine { pub(crate) fn exec_fn_call( &self, state: &mut State, - lib: &Module, + lib: &[&Module], fn_name: &str, hash_script: u64, args: &mut FnCallArgs, @@ -543,13 +541,14 @@ impl Engine { // Script-like function found #[cfg(not(feature = "no_function"))] - _ if lib.contains_fn(hash_script, pub_only) + _ if lib.iter().any(|&m| m.contains_fn(hash_script, pub_only)) //|| self.global_module.contains_fn(hash_script, pub_only) || self.packages.contains_fn(hash_script, pub_only) => { // Get function let func = lib - .get_fn(hash_script, pub_only) + .iter() + .find_map(|&m| m.get_fn(hash_script, pub_only)) //.or_else(|| self.global_module.get_fn(hash_script, pub_only)) .or_else(|| self.packages.get_fn(hash_script, pub_only)) .unwrap(); @@ -557,8 +556,8 @@ impl Engine { if func.is_script() { let func = func.get_fn_def(); - let scope = &mut Scope::new(); - let mods = &mut Imports::new(); + let scope: &mut Scope = &mut Default::default(); + let mods = &mut Default::default(); // Move captured variables into scope #[cfg(not(feature = "no_closure"))] @@ -634,6 +633,30 @@ impl Engine { } } + /// Evaluate a list of statements. + #[inline] + pub(crate) fn eval_statements<'a>( + &self, + scope: &mut Scope, + mods: &mut Imports, + statements: impl IntoIterator, + lib: &[&Module], + ) -> Result<(Dynamic, u64), Box> { + let mut state = State::new(); + + statements + .into_iter() + .try_fold(().into(), |_, stmt| { + self.eval_stmt(scope, mods, &mut state, lib, &mut None, stmt, 0) + }) + .or_else(|err| match *err { + EvalAltResult::Return(out, _) => Ok(out), + EvalAltResult::LoopBreak(_, _) => unreachable!(), + _ => Err(err), + }) + .map(|v| (v, state.operations)) + } + /// Evaluate a text string as a script - used primarily for 'eval'. /// Position in `EvalAltResult` is `None` and must be set afterwards. fn eval_script_expr( @@ -641,7 +664,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], script: &str, _level: usize, ) -> Result> { @@ -658,8 +681,8 @@ impl Engine { // Compile the script text // No optimizations because we only run it once - let mut ast = self.compile_with_scope_and_optimization_level( - &Scope::new(), + let ast = self.compile_with_scope_and_optimization_level( + &Default::default(), &[script], OptimizationLevel::None, )?; @@ -669,11 +692,8 @@ impl Engine { return Err(ParseErrorType::WrongFnDefinition.into()); } - let statements = mem::take(ast.statements_mut()); - let ast = AST::new(statements, lib.clone()); - // Evaluate the AST - let (result, operations) = self.eval_ast_with_scope_raw(scope, mods, &ast)?; + let (result, operations) = self.eval_statements(scope, mods, ast.statements(), lib)?; state.operations += operations; self.inc_operations(state)?; @@ -687,7 +707,7 @@ impl Engine { pub(crate) fn make_method_call( &self, state: &mut State, - lib: &Module, + lib: &[&Module], name: &str, hash_script: u64, target: &mut Target, @@ -839,7 +859,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, name: &str, args_expr: impl AsRef<[Expr]>, @@ -984,7 +1004,7 @@ impl Engine { return Ok(false.into()); } else { let hash = calc_fn_hash(empty(), fn_name, num_params as usize, empty()); - return Ok(lib.contains_fn(hash, false).into()); + return Ok(lib.iter().any(|&m| m.contains_fn(hash, false)).into()); } } } @@ -1085,7 +1105,7 @@ impl Engine { scope: &mut Scope, mods: &mut Imports, state: &mut State, - lib: &Module, + lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, modules: &Option>, name: &str, @@ -1186,8 +1206,8 @@ impl Engine { let args = args.as_mut(); let fn_def = f.get_fn_def(); - let new_scope = &mut Scope::new(); - let mods = &mut Imports::new(); + let new_scope = &mut Default::default(); + let mods = &mut Default::default(); self.call_script_fn(new_scope, mods, state, lib, &mut None, fn_def, args, level) } diff --git a/src/fn_native.rs b/src/fn_native.rs index c37c8b28..a41d6623 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -50,29 +50,31 @@ pub type Locked = RwLock; /// Context of native Rust function call. #[derive(Debug, Copy, Clone)] -pub struct NativeCallContext<'e, 'm> { +pub struct NativeCallContext<'e, 'm, 'pm: 'm> { engine: &'e Engine, - lib: &'m Module, + lib: &'m [&'pm Module], } -impl<'e, 'm> From<(&'e Engine, &'m Module)> for NativeCallContext<'e, 'm> { - fn from(value: (&'e Engine, &'m Module)) -> Self { +impl<'e, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> From<(&'e Engine, &'m M)> + for NativeCallContext<'e, 'm, 'pm> +{ + fn from(value: (&'e Engine, &'m M)) -> Self { Self { engine: value.0, - lib: value.1, + lib: value.1.as_ref(), } } } -impl<'e, 'm> NativeCallContext<'e, 'm> { +impl<'e, 'm, 'pm> NativeCallContext<'e, 'm, 'pm> { /// The current `Engine`. #[inline(always)] pub fn engine(&self) -> &'e Engine { self.engine } - /// The global namespace containing definition of all script-defined functions. + /// The chain of namespaces containing definition of all script-defined functions. #[inline(always)] - pub fn namespace(&self) -> &'m Module { + pub fn namespaces(&self) -> &'m [&'pm Module] { self.lib } } @@ -184,7 +186,7 @@ impl FnPtr { .engine() .exec_fn_call( &mut Default::default(), - context.namespace(), + context.namespaces(), fn_name, hash_script, args.as_mut(), diff --git a/src/optimize.rs b/src/optimize.rs index 631f68d6..0e6db3d5 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -70,7 +70,7 @@ struct State<'a> { /// An `Engine` instance for eager function evaluation. engine: &'a Engine, /// Library of script-defined functions. - lib: &'a Module, + lib: &'a [&'a Module], /// Optimization level. optimization_level: OptimizationLevel, } @@ -78,7 +78,7 @@ struct State<'a> { impl<'a> State<'a> { /// Create a new State. #[inline(always)] - pub fn new(engine: &'a Engine, lib: &'a Module, level: OptimizationLevel) -> Self { + pub fn new(engine: &'a Engine, lib: &'a [&'a Module], level: OptimizationLevel) -> Self { Self { changed: false, constants: vec![], @@ -615,7 +615,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr { // First search for script-defined functions (can override built-in) #[cfg(not(feature = "no_function"))] - let has_script_fn = state.lib.get_script_fn(name, args.len(), false).is_some(); + let has_script_fn = state.lib.iter().any(|&m| m.get_script_fn(name, args.len(), false).is_some()); #[cfg(feature = "no_function")] let has_script_fn = false; @@ -686,7 +686,7 @@ fn optimize( statements: Vec, engine: &Engine, scope: &Scope, - lib: &Module, + lib: &[&Module], level: OptimizationLevel, ) -> Vec { // If optimization level is None then skip optimizing @@ -837,7 +837,8 @@ pub fn optimize_into_ast( let pos = fn_def.body.position(); // Optimize the function body - let mut body = optimize(vec![fn_def.body], engine, &Scope::new(), &lib2, level); + let mut body = + optimize(vec![fn_def.body], engine, &Scope::new(), &[&lib2], level); // {} -> Noop fn_def.body = match body.pop().unwrap_or_else(|| Stmt::Noop(pos)) { @@ -877,7 +878,7 @@ pub fn optimize_into_ast( match level { OptimizationLevel::None => statements, OptimizationLevel::Simple | OptimizationLevel::Full => { - optimize(statements, engine, &scope, &lib, level) + optimize(statements, engine, &scope, &[&lib], level) } }, lib, diff --git a/src/syntax.rs b/src/syntax.rs index 4e305f41..5d3b8a02 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -53,7 +53,7 @@ impl Expression<'_> { } } -impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> { +impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> { /// Evaluate an expression tree. /// /// ## WARNING - Low Level API @@ -68,7 +68,7 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> { self.scope, self.mods, self.state, - self.namespace(), + self.namespaces(), self.this_ptr, expr.expr(), self.call_level(), diff --git a/tests/closures.rs b/tests/closures.rs index 4f5f1b17..1d80f46e 100644 --- a/tests/closures.rs +++ b/tests/closures.rs @@ -270,7 +270,7 @@ fn test_closures_external() -> Result<(), Box> { ast.retain_functions(|_, _, _| true); // Closure 'f' captures: the engine, the AST, and the curried function pointer - let f = move |x: INT| fn_ptr.call_dynamic((&engine, ast.as_ref()).into(), None, [x.into()]); + let f = move |x: INT| fn_ptr.call_dynamic((&engine, &[ast.as_ref()]).into(), None, [x.into()]); assert_eq!(f(42)?.as_str(), Ok("hello42"));