Reduce duplicated generics code.

This commit is contained in:
Stephen Chung 2021-09-07 23:05:31 +08:00
parent 09da9ddcbc
commit 7956f9d59c
2 changed files with 76 additions and 69 deletions

View File

@ -1338,6 +1338,7 @@ impl Engine {
/// # } /// # }
/// ``` /// ```
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline(always)]
pub fn parse_json( pub fn parse_json(
&self, &self,
json: impl AsRef<str>, json: impl AsRef<str>,
@ -1345,52 +1346,51 @@ impl Engine {
) -> Result<Map, Box<EvalAltResult>> { ) -> Result<Map, Box<EvalAltResult>> {
use crate::token::Token; use crate::token::Token;
let json = json.as_ref(); fn parse_json_inner(
let mut scope = Default::default(); engine: &Engine,
json: &str,
// Trims the JSON string and add a '#' in front has_null: bool,
let json_text = json.trim_start(); ) -> Result<Map, Box<EvalAltResult>> {
let scripts = if json_text.starts_with(Token::MapStart.literal_syntax()) { let mut scope = Default::default();
[json_text, ""] let json_text = json.trim_start();
} else if json_text.starts_with(Token::LeftBrace.literal_syntax()) { let scripts = if json_text.starts_with(Token::MapStart.literal_syntax()) {
["#", json_text] [json_text, ""]
} else { } else if json_text.starts_with(Token::LeftBrace.literal_syntax()) {
return Err(crate::ParseErrorType::MissingToken( ["#", json_text]
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,
}
} else { } else {
|t| t return Err(crate::ParseErrorType::MissingToken(
}), Token::LeftBrace.syntax().into(),
); "to start a JSON object hash".into(),
)
let mut state = ParseState::new(self, tokenizer_control); .into_err(Position::new(1, (json.len() - json_text.len() + 1) as u16))
.into());
let ast = self.parse_global_expr( };
&mut stream.peekable(), let (stream, tokenizer_control) = engine.lex_raw(
&mut state, &scripts,
&scope, Some(if has_null {
OptimizationLevel::None, |token| match token {
)?; // If `null` is present, make sure `null` is treated as a variable
Token::Reserved(s) if s == "null" => Token::Identifier(s),
// Handle null - map to () _ => token,
if has_null { }
scope.push_constant("null", ()); } 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`], /// Compile a string containing an expression into an [`AST`],
/// which can be used later for evaluation. /// which can be used later for evaluation.

View File

@ -192,39 +192,46 @@ impl<'a> NativeCallContext<'a> {
/// ///
/// If `is_method` is [`true`], the first argument is assumed to be passed /// If `is_method` is [`true`], the first argument is assumed to be passed
/// by reference and is not consumed. /// by reference and is not consumed.
#[inline] #[inline(always)]
pub fn call_fn_dynamic_raw( pub fn call_fn_dynamic_raw(
&self, &self,
fn_name: impl AsRef<str>, fn_name: impl AsRef<str>,
is_method_call: bool, is_method_call: bool,
args: &mut [&mut Dynamic], args: &mut [&mut Dynamic],
) -> RhaiResult { ) -> 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<Dynamic, Box<EvalAltResult>> {
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 { call_fn_dynamic_inner(self, is_method_call, fn_name.as_ref(), args)
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)
} }
} }