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"))]
#[inline(always)]
pub fn parse_json(
&self,
json: impl AsRef<str>,
@ -1345,52 +1346,51 @@ impl Engine {
) -> Result<Map, Box<EvalAltResult>> {
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<Map, Box<EvalAltResult>> {
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.

View File

@ -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<str>,
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<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 {
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)
}
}