From 7956f9d59c413da14df1483f64718dcdac5c7cbd Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 7 Sep 2021 23:05:31 +0800 Subject: [PATCH] Reduce duplicated generics code. --- src/engine_api.rs | 86 +++++++++++++++++++++++------------------------ src/fn_native.rs | 59 ++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 69 deletions(-) diff --git a/src/engine_api.rs b/src/engine_api.rs index 18918215..40c24c17 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -1338,6 +1338,7 @@ impl Engine { /// # } /// ``` #[cfg(not(feature = "no_object"))] + #[inline(always)] pub fn parse_json( &self, json: impl AsRef, @@ -1345,52 +1346,51 @@ impl Engine { ) -> Result> { use crate::token::Token; - let json = json.as_ref(); - let mut scope = Default::default(); - - // Trims the JSON string and add a '#' in front - let json_text = json.trim_start(); - let scripts = if json_text.starts_with(Token::MapStart.literal_syntax()) { - [json_text, ""] - } else if json_text.starts_with(Token::LeftBrace.literal_syntax()) { - ["#", json_text] - } else { - return Err(crate::ParseErrorType::MissingToken( - Token::LeftBrace.syntax().into(), - "to start a JSON object hash".into(), - ) - .into_err(Position::new(1, (json.len() - json_text.len() + 1) as u16)) - .into()); - }; - - let (stream, tokenizer_control) = self.lex_raw( - &scripts, - Some(if has_null { - |token| match token { - // If `null` is present, make sure `null` is treated as a variable - Token::Reserved(s) if s == "null" => Token::Identifier(s), - _ => token, - } + fn parse_json_inner( + engine: &Engine, + json: &str, + has_null: bool, + ) -> Result> { + let mut scope = Default::default(); + let json_text = json.trim_start(); + let scripts = if json_text.starts_with(Token::MapStart.literal_syntax()) { + [json_text, ""] + } else if json_text.starts_with(Token::LeftBrace.literal_syntax()) { + ["#", json_text] } else { - |t| t - }), - ); - - let mut state = ParseState::new(self, tokenizer_control); - - let ast = self.parse_global_expr( - &mut stream.peekable(), - &mut state, - &scope, - OptimizationLevel::None, - )?; - - // Handle null - map to () - if has_null { - scope.push_constant("null", ()); + return Err(crate::ParseErrorType::MissingToken( + Token::LeftBrace.syntax().into(), + "to start a JSON object hash".into(), + ) + .into_err(Position::new(1, (json.len() - json_text.len() + 1) as u16)) + .into()); + }; + let (stream, tokenizer_control) = engine.lex_raw( + &scripts, + Some(if has_null { + |token| match token { + // If `null` is present, make sure `null` is treated as a variable + Token::Reserved(s) if s == "null" => Token::Identifier(s), + _ => token, + } + } else { + |t| t + }), + ); + let mut state = ParseState::new(engine, tokenizer_control); + let ast = engine.parse_global_expr( + &mut stream.peekable(), + &mut state, + &scope, + OptimizationLevel::None, + )?; + if has_null { + scope.push_constant("null", ()); + } + engine.eval_ast_with_scope(&mut scope, &ast) } - self.eval_ast_with_scope(&mut scope, &ast) + parse_json_inner(self, json.as_ref(), has_null) } /// Compile a string containing an expression into an [`AST`], /// which can be used later for evaluation. diff --git a/src/fn_native.rs b/src/fn_native.rs index cf7b9d1c..a5cc3bc5 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -192,39 +192,46 @@ impl<'a> NativeCallContext<'a> { /// /// If `is_method` is [`true`], the first argument is assumed to be passed /// by reference and is not consumed. - #[inline] + #[inline(always)] pub fn call_fn_dynamic_raw( &self, fn_name: impl AsRef, is_method_call: bool, args: &mut [&mut Dynamic], ) -> RhaiResult { - let fn_name = fn_name.as_ref(); + fn call_fn_dynamic_inner( + context: &NativeCallContext, + is_method_call: bool, + fn_name: &str, + args: &mut [&mut Dynamic], + ) -> Result> { + let hash = if is_method_call { + FnCallHashes::from_script_and_native( + calc_fn_hash(fn_name, args.len() - 1), + calc_fn_hash(fn_name, args.len()), + ) + } else { + FnCallHashes::from_script(calc_fn_hash(fn_name, args.len())) + }; + context + .engine() + .exec_fn_call( + &mut context.mods.cloned().unwrap_or_default(), + &mut Default::default(), + context.lib, + fn_name, + hash, + args, + is_method_call, + is_method_call, + Position::NONE, + None, + 0, + ) + .map(|(r, _)| r) + } - let hash = if is_method_call { - FnCallHashes::from_script_and_native( - calc_fn_hash(fn_name, args.len() - 1), - calc_fn_hash(fn_name, args.len()), - ) - } else { - FnCallHashes::from_script(calc_fn_hash(fn_name, args.len())) - }; - - self.engine() - .exec_fn_call( - &mut self.mods.cloned().unwrap_or_default(), - &mut Default::default(), - self.lib, - fn_name, - hash, - args, - is_method_call, - is_method_call, - Position::NONE, - None, - 0, - ) - .map(|(r, _)| r) + call_fn_dynamic_inner(self, is_method_call, fn_name.as_ref(), args) } }