Refactor FnCallHashes.

This commit is contained in:
Stephen Chung 2023-02-11 12:52:07 +08:00
parent e177a5648a
commit 9cb5154979
4 changed files with 88 additions and 63 deletions

View File

@ -124,34 +124,35 @@ impl fmt::Debug for FnCallHashes {
} }
} }
impl From<u64> for FnCallHashes { impl FnCallHashes {
/// Create a [`FnCallHashes`] from a single hash.
#[inline] #[inline]
fn from(hash: u64) -> Self { #[must_use]
pub const fn from_hash(hash: u64) -> Self {
Self { Self {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
script: Some(hash), script: Some(hash),
native: hash, native: hash,
} }
} }
}
impl FnCallHashes {
/// Create a [`FnCallHashes`] with only the native Rust hash. /// Create a [`FnCallHashes`] with only the native Rust hash.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn from_native(hash: u64) -> Self { pub const fn from_native_only(hash: u64) -> Self {
Self { Self {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
script: None, script: None,
native: hash, native: hash,
} }
} }
/// Create a [`FnCallHashes`] with both native Rust and script function hashes. /// Create a [`FnCallHashes`] with both script function and native Rust hashes.
///
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))]
#[inline] #[inline]
#[must_use] #[must_use]
pub fn from_all(#[cfg(not(feature = "no_function"))] script: u64, native: u64) -> Self { pub const fn from_script_and_native(script: u64, native: u64) -> Self {
Self { Self {
#[cfg(not(feature = "no_function"))]
script: Some(script), script: Some(script),
native, native,
} }
@ -577,7 +578,7 @@ impl Expr {
FnCallExpr { FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: KEYWORD_FN_PTR.into(), name: KEYWORD_FN_PTR.into(),
hashes: calc_fn_hash(None, f.fn_name(), 1).into(), hashes: FnCallHashes::from_hash(calc_fn_hash(None, f.fn_name(), 1)),
args: once(Self::StringConstant(f.fn_name().into(), pos)).collect(), args: once(Self::StringConstant(f.fn_name().into(), pos)).collect(),
capture_parent_scope: false, capture_parent_scope: false,
op_token: None, op_token: None,

View File

@ -785,9 +785,9 @@ impl Engine {
let fn_name = fn_ptr.fn_name(); let fn_name = fn_ptr.fn_name();
// Recalculate hashes // Recalculate hashes
let new_hash = if !is_anon && !is_valid_function_name(fn_name) { let new_hash = if !is_anon && !is_valid_function_name(fn_name) {
FnCallHashes::from_native(calc_fn_hash(None, fn_name, args.len())) FnCallHashes::from_native_only(calc_fn_hash(None, fn_name, args.len()))
} else { } else {
calc_fn_hash(None, fn_name, args.len()).into() FnCallHashes::from_hash(calc_fn_hash(None, fn_name, args.len()))
}; };
// Map it to name(args) in function-call style // Map it to name(args) in function-call style
@ -867,14 +867,17 @@ impl Engine {
args.insert(0, target.as_mut()); args.insert(0, target.as_mut());
// Recalculate hash // Recalculate hash
let new_hash = if !is_anon && !is_valid_function_name(&fn_name) { let new_hash = match is_anon {
FnCallHashes::from_native(calc_fn_hash(None, &fn_name, args.len())) false if !is_valid_function_name(&fn_name) => {
} else { FnCallHashes::from_native_only(calc_fn_hash(None, &fn_name, args.len()))
FnCallHashes::from_all( }
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
_ => FnCallHashes::from_script_and_native(
calc_fn_hash(None, &fn_name, args.len() - 1), calc_fn_hash(None, &fn_name, args.len() - 1),
calc_fn_hash(None, &fn_name, args.len()), calc_fn_hash(None, &fn_name, args.len()),
) ),
#[cfg(feature = "no_function")]
_ => FnCallHashes::from_native_only(calc_fn_hash(None, &fn_name, args.len())),
}; };
// Map it to name(args) in function-call style // Map it to name(args) in function-call style
@ -943,18 +946,22 @@ impl Engine {
call_args = &mut _arg_values; call_args = &mut _arg_values;
} }
// Recalculate the hash based on the new function name and new arguments // Recalculate the hash based on the new function name and new arguments
hash = if !is_anon && !is_valid_function_name(fn_name) { let args_len = call_args.len() + 1;
FnCallHashes::from_native(calc_fn_hash( hash = match is_anon {
None, false if !is_valid_function_name(fn_name) => {
fn_name, FnCallHashes::from_native_only(calc_fn_hash(
call_args.len() + 1, None, fn_name, args_len,
)) ))
} else { }
FnCallHashes::from_all( #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_function"))] _ => FnCallHashes::from_script_and_native(
calc_fn_hash(None, fn_name, call_args.len()), calc_fn_hash(None, fn_name, args_len - 1),
calc_fn_hash(None, fn_name, call_args.len() + 1), calc_fn_hash(None, fn_name, args_len),
) ),
#[cfg(feature = "no_function")]
_ => FnCallHashes::from_native_only(calc_fn_hash(
None, fn_name, args_len,
)),
}; };
} }
} }
@ -1080,9 +1087,9 @@ impl Engine {
let args_len = total_args + curry.len(); let args_len = total_args + curry.len();
hashes = if !is_anon && !is_valid_function_name(name) { hashes = if !is_anon && !is_valid_function_name(name) {
FnCallHashes::from_native(calc_fn_hash(None, name, args_len)) FnCallHashes::from_native_only(calc_fn_hash(None, name, args_len))
} else { } else {
calc_fn_hash(None, name, args_len).into() FnCallHashes::from_hash(calc_fn_hash(None, name, args_len))
}; };
} }
// Handle Fn() // Handle Fn()

View File

@ -457,14 +457,15 @@ impl<'a> NativeCallContext<'a> {
// Native or script // Native or script
let hash = if is_method_call { let hash = match is_method_call {
FnCallHashes::from_all( #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_function"))] true => FnCallHashes::from_script_and_native(
calc_fn_hash(None, fn_name, args_len - 1), calc_fn_hash(None, fn_name, args_len - 1),
calc_fn_hash(None, fn_name, args_len), calc_fn_hash(None, fn_name, args_len),
) ),
} else { #[cfg(feature = "no_function")]
calc_fn_hash(None, fn_name, args_len).into() true => FnCallHashes::from_native_only(calc_fn_hash(None, fn_name, args_len)),
_ => FnCallHashes::from_hash(calc_fn_hash(None, fn_name, args_len)),
}; };
self.engine() self.engine()

View File

@ -625,9 +625,9 @@ impl Engine {
let hash = calc_fn_hash(None, &id, 0); let hash = calc_fn_hash(None, &id, 0);
let hashes = if is_valid_function_name(&id) { let hashes = if is_valid_function_name(&id) {
hash.into() FnCallHashes::from_hash(hash)
} else { } else {
FnCallHashes::from_native(hash) FnCallHashes::from_native_only(hash)
}; };
args.shrink_to_fit(); args.shrink_to_fit();
@ -700,9 +700,9 @@ impl Engine {
let hash = calc_fn_hash(None, &id, args.len()); let hash = calc_fn_hash(None, &id, args.len());
let hashes = if is_valid_function_name(&id) { let hashes = if is_valid_function_name(&id) {
hash.into() FnCallHashes::from_hash(hash)
} else { } else {
FnCallHashes::from_native(hash) FnCallHashes::from_native_only(hash)
}; };
args.shrink_to_fit(); args.shrink_to_fit();
@ -1952,7 +1952,7 @@ impl Engine {
Ok(FnCallExpr { Ok(FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string("-"), name: state.get_interned_string("-"),
hashes: FnCallHashes::from_native(calc_fn_hash(None, "-", 1)), hashes: FnCallHashes::from_native_only(calc_fn_hash(None, "-", 1)),
args, args,
op_token: Some(token), op_token: Some(token),
capture_parent_scope: false, capture_parent_scope: false,
@ -1980,7 +1980,7 @@ impl Engine {
Ok(FnCallExpr { Ok(FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string("+"), name: state.get_interned_string("+"),
hashes: FnCallHashes::from_native(calc_fn_hash(None, "+", 1)), hashes: FnCallHashes::from_native_only(calc_fn_hash(None, "+", 1)),
args, args,
op_token: Some(token), op_token: Some(token),
capture_parent_scope: false, capture_parent_scope: false,
@ -2001,7 +2001,7 @@ impl Engine {
Ok(FnCallExpr { Ok(FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string("!"), name: state.get_interned_string("!"),
hashes: FnCallHashes::from_native(calc_fn_hash(None, "!", 1)), hashes: FnCallHashes::from_native_only(calc_fn_hash(None, "!", 1)),
args, args,
op_token: Some(token), op_token: Some(token),
capture_parent_scope: false, capture_parent_scope: false,
@ -2180,14 +2180,21 @@ impl Engine {
// lhs.func(...) // lhs.func(...)
(lhs, Expr::FnCall(mut f, func_pos)) => { (lhs, Expr::FnCall(mut f, func_pos)) => {
// Recalculate hash // Recalculate hash
let args_len = f.args.len() + 1;
f.hashes = if is_valid_function_name(&f.name) { f.hashes = if is_valid_function_name(&f.name) {
FnCallHashes::from_all( #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_function"))] {
calc_fn_hash(None, &f.name, f.args.len()), FnCallHashes::from_script_and_native(
calc_fn_hash(None, &f.name, f.args.len() + 1), calc_fn_hash(None, &f.name, args_len - 1),
) calc_fn_hash(None, &f.name, args_len),
)
}
#[cfg(feature = "no_function")]
{
FnCallHashes::from_native_only(calc_fn_hash(None, &f.name, args_len))
}
} else { } else {
FnCallHashes::from_native(calc_fn_hash(None, &f.name, f.args.len() + 1)) FnCallHashes::from_native_only(calc_fn_hash(None, &f.name, args_len))
}; };
let rhs = Expr::MethodCall(f, func_pos); let rhs = Expr::MethodCall(f, func_pos);
@ -2228,14 +2235,23 @@ impl Engine {
// lhs.func().dot_rhs or lhs.func()[idx_rhs] // lhs.func().dot_rhs or lhs.func()[idx_rhs]
Expr::FnCall(mut f, func_pos) => { Expr::FnCall(mut f, func_pos) => {
// Recalculate hash // Recalculate hash
let args_len = f.args.len() + 1;
f.hashes = if is_valid_function_name(&f.name) { f.hashes = if is_valid_function_name(&f.name) {
FnCallHashes::from_all( #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "no_function"))] {
calc_fn_hash(None, &f.name, f.args.len()), FnCallHashes::from_script_and_native(
calc_fn_hash(None, &f.name, f.args.len() + 1), calc_fn_hash(None, &f.name, args_len - 1),
) calc_fn_hash(None, &f.name, args_len),
)
}
#[cfg(feature = "no_function")]
{
FnCallHashes::from_native_only(calc_fn_hash(
None, &f.name, args_len,
))
}
} else { } else {
FnCallHashes::from_native(calc_fn_hash(None, &f.name, f.args.len() + 1)) FnCallHashes::from_native_only(calc_fn_hash(None, &f.name, args_len))
}; };
let new_lhs = BinaryExpr { let new_lhs = BinaryExpr {
@ -2351,7 +2367,7 @@ impl Engine {
let mut op_base = FnCallExpr { let mut op_base = FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string(&op), name: state.get_interned_string(&op),
hashes: FnCallHashes::from_native(hash), hashes: FnCallHashes::from_native_only(hash),
args, args,
op_token: operator_token, op_token: operator_token,
capture_parent_scope: false, capture_parent_scope: false,
@ -2394,7 +2410,7 @@ impl Engine {
op_base.args.shrink_to_fit(); op_base.args.shrink_to_fit();
// Convert into a call to `contains` // Convert into a call to `contains`
op_base.hashes = calc_fn_hash(None, OP_CONTAINS, 2).into(); op_base.hashes = FnCallHashes::from_hash(calc_fn_hash(None, OP_CONTAINS, 2));
op_base.name = state.get_interned_string(OP_CONTAINS); op_base.name = state.get_interned_string(OP_CONTAINS);
let fn_call = op_base.into_fn_call_expr(pos); let fn_call = op_base.into_fn_call_expr(pos);
@ -2409,7 +2425,7 @@ impl Engine {
let not_base = FnCallExpr { let not_base = FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string(op), name: state.get_interned_string(op),
hashes: FnCallHashes::from_native(calc_fn_hash(None, op, 1)), hashes: FnCallHashes::from_native_only(calc_fn_hash(None, op, 1)),
args, args,
op_token: Some(Token::Bang), op_token: Some(Token::Bang),
capture_parent_scope: false, capture_parent_scope: false,
@ -2427,9 +2443,9 @@ impl Engine {
.map_or(false, Option::is_some) => .map_or(false, Option::is_some) =>
{ {
op_base.hashes = if is_valid_script_function { op_base.hashes = if is_valid_script_function {
calc_fn_hash(None, &s, 2).into() FnCallHashes::from_hash(calc_fn_hash(None, &s, 2))
} else { } else {
FnCallHashes::from_native(calc_fn_hash(None, &s, 2)) FnCallHashes::from_native_only(calc_fn_hash(None, &s, 2))
}; };
op_base.into_fn_call_expr(pos) op_base.into_fn_call_expr(pos)
} }
@ -3709,7 +3725,7 @@ impl Engine {
let expr = FnCallExpr { let expr = FnCallExpr {
namespace: Namespace::NONE, namespace: Namespace::NONE,
name: state.get_interned_string(crate::engine::KEYWORD_FN_PTR_CURRY), name: state.get_interned_string(crate::engine::KEYWORD_FN_PTR_CURRY),
hashes: FnCallHashes::from_native(calc_fn_hash( hashes: FnCallHashes::from_native_only(calc_fn_hash(
None, None,
crate::engine::KEYWORD_FN_PTR_CURRY, crate::engine::KEYWORD_FN_PTR_CURRY,
num_externals + 1, num_externals + 1,