diff --git a/src/api/call_fn.rs b/src/api/call_fn.rs index d6290163..1f2ec085 100644 --- a/src/api/call_fn.rs +++ b/src/api/call_fn.rs @@ -187,7 +187,7 @@ impl Engine { /// /// # WARNING - Low Level API /// - /// This function is very low level. + /// This function is _extremely_ low level. /// /// A [`GlobalRuntimeState`] and [`Caches`] need to be passed into the function, which can be /// created via [`GlobalRuntimeState::new`] and [`Caches::new`]. diff --git a/src/ast/namespace.rs b/src/ast/namespace.rs index 22103d5d..9bf328dd 100644 --- a/src/ast/namespace.rs +++ b/src/ast/namespace.rs @@ -17,8 +17,8 @@ use std::{ /// /// Not available under `no_module`. /// -/// A [`u64`] offset to the current [stack of imported modules][crate::GlobalRuntimeState] is -/// cached for quick search purposes. +/// A [`u64`] offset to the current stack of imported [modules][crate::Module] in the +/// [global runtime state][crate::GlobalRuntimeState] is cached for quick search purposes. /// /// A [`StaticVec`] is used because the vast majority of namespace-qualified access contains only /// one level, and it is wasteful to always allocate a [`Vec`] with one element. diff --git a/src/func/call.rs b/src/func/call.rs index cfeebacb..edc07ae3 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -736,6 +736,42 @@ impl Engine { }) } + /// Evaluate an argument. + #[inline] + pub(crate) fn get_arg_value( + &self, + scope: &mut Scope, + global: &mut GlobalRuntimeState, + caches: &mut Caches, + lib: &[&Module], + this_ptr: &mut Option<&mut Dynamic>, + arg_expr: &Expr, + level: usize, + ) -> RhaiResultOf<(Dynamic, Position)> { + #[cfg(feature = "debugging")] + if self.debugger.is_some() { + if let Some(value) = arg_expr.get_literal_value() { + #[cfg(feature = "debugging")] + self.run_debugger(scope, global, lib, this_ptr, arg_expr, level)?; + return Ok((value, arg_expr.start_position())); + } + } + + // Do not match function exit for arguments + #[cfg(feature = "debugging")] + let reset_debugger = global.debugger.clear_status_if(|status| { + matches!(status, crate::eval::DebuggerStatus::FunctionExit(..)) + }); + + let result = self.eval_expr(scope, global, caches, lib, this_ptr, arg_expr, level); + + // Restore function exit status + #[cfg(feature = "debugging")] + global.debugger.reset_status(reset_debugger); + + Ok((result?, arg_expr.start_position())) + } + /// Call a dot method. #[cfg(not(feature = "no_object"))] pub(crate) fn make_method_call( @@ -892,42 +928,6 @@ impl Engine { Ok((result, updated)) } - /// Evaluate an argument. - #[inline] - pub(crate) fn get_arg_value( - &self, - scope: &mut Scope, - global: &mut GlobalRuntimeState, - caches: &mut Caches, - lib: &[&Module], - this_ptr: &mut Option<&mut Dynamic>, - arg_expr: &Expr, - level: usize, - ) -> RhaiResultOf<(Dynamic, Position)> { - #[cfg(feature = "debugging")] - if self.debugger.is_some() { - if let Some(value) = arg_expr.get_literal_value() { - #[cfg(feature = "debugging")] - self.run_debugger(scope, global, lib, this_ptr, arg_expr, level)?; - return Ok((value, arg_expr.start_position())); - } - } - - // Do not match function exit for arguments - #[cfg(feature = "debugging")] - let reset_debugger = global.debugger.clear_status_if(|status| { - matches!(status, crate::eval::DebuggerStatus::FunctionExit(..)) - }); - - let result = self.eval_expr(scope, global, caches, lib, this_ptr, arg_expr, level); - - // Restore function exit status - #[cfg(feature = "debugging")] - global.debugger.reset_status(reset_debugger); - - Ok((result?, arg_expr.start_position())) - } - /// Call a function in normal function-call style. pub(crate) fn make_function_call( &self, diff --git a/src/parser.rs b/src/parser.rs index 5ab4b0b1..6726d1fe 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -387,6 +387,7 @@ fn match_token(input: &mut TokenStream, token: Token) -> (bool, Position) { } /// Parse a variable name. +#[inline] fn parse_var_name(input: &mut TokenStream) -> ParseResult<(SmartString, Position)> { match input.next().expect(NEVER_ENDS) { // Variable name @@ -403,6 +404,7 @@ fn parse_var_name(input: &mut TokenStream) -> ParseResult<(SmartString, Position } /// Parse a symbol. +#[inline] fn parse_symbol(input: &mut TokenStream) -> ParseResult<(SmartString, Position)> { match input.next().expect(NEVER_ENDS) { // Symbol @@ -631,7 +633,7 @@ impl Engine { state: &mut ParseState, lib: &mut FnLib, lhs: Expr, - chained: bool, + check_index_type: bool, settings: ParseSettings, ) -> ParseResult { #[cfg(not(feature = "unchecked"))] @@ -644,7 +646,7 @@ impl Engine { // Check types of indexing that cannot be overridden // - arrays, maps, strings, bit-fields match lhs { - _ if chained => (), + _ if !check_index_type => (), Expr::Map(..) => match idx_expr { // lhs[int] @@ -755,7 +757,7 @@ impl Engine { state, lib, idx_expr, - true, + false, settings.level_up(), )?; // Indexing binds to right @@ -1617,7 +1619,7 @@ impl Engine { // Indexing #[cfg(not(feature = "no_index"))] (expr, Token::LeftBracket) => { - self.parse_index_chain(input, state, lib, expr, false, settings.level_up())? + self.parse_index_chain(input, state, lib, expr, true, settings.level_up())? } // Property access #[cfg(not(feature = "no_object"))] @@ -2704,15 +2706,16 @@ impl Engine { nesting_level: level, will_shadow, }; - let context = EvalContext { - engine: self, - scope: &mut state.stack, - global: &mut state.global, - caches: None, - lib: &[], - this_ptr: &mut None, + let mut this_ptr = None; + let context = EvalContext::new( + self, + &mut state.stack, + &mut state.global, + None, + &[], + &mut this_ptr, level, - }; + ); match filter(false, info, context) { Ok(true) => (),