Streamline hashing function.

This commit is contained in:
Stephen Chung 2021-05-19 20:26:11 +08:00
parent 85a5aa14b3
commit 1545b602a7
9 changed files with 92 additions and 117 deletions

View File

@ -13,7 +13,6 @@ use std::{
collections::BTreeMap, collections::BTreeMap,
fmt, fmt,
hash::Hash, hash::Hash,
iter::empty,
mem, mem,
num::{NonZeroU8, NonZeroUsize}, num::{NonZeroU8, NonZeroUsize},
ops::{Add, AddAssign, Deref, DerefMut}, ops::{Add, AddAssign, Deref, DerefMut},
@ -1404,8 +1403,8 @@ impl OpAssignment {
let op_assignment = op.keyword_syntax(); let op_assignment = op.keyword_syntax();
Self { Self {
hash_op_assign: calc_fn_hash(empty(), op_assignment, 2), hash_op_assign: calc_fn_hash(op_assignment, 2),
hash_op: calc_fn_hash(empty(), op_raw, 2), hash_op: calc_fn_hash(op_raw, 2),
op: op_assignment, op: op_assignment,
} }
} }

View File

@ -29,7 +29,7 @@ use std::{
}; };
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
use crate::{calc_fn_hash, Array}; use crate::Array;
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
use crate::Map; use crate::Map;
@ -1166,61 +1166,40 @@ impl Engine {
} }
// xxx[rhs] op= new_val // xxx[rhs] op= new_val
_ if new_val.is_some() => { _ if new_val.is_some() => {
let ((mut new_val, new_pos), (op_info, op_pos)) = new_val.unwrap();
let idx_val = idx_val.as_index_value(); let idx_val = idx_val.as_index_value();
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
let mut idx_val2 = idx_val.clone(); let mut idx_val_for_setter = idx_val.clone();
// `call_setter` is introduced to bypass double mutable borrowing of target match self.get_indexed_mut(
let _call_setter = match self.get_indexed_mut(
mods, state, lib, target, idx_val, pos, true, false, level, mods, state, lib, target, idx_val, pos, true, false, level,
) { ) {
// Indexed value is a reference - update directly // Indexed value is a reference - update directly
Ok(obj_ptr) => { Ok(obj_ptr) => {
let ((new_val, new_pos), (op_info, op_pos)) = new_val.unwrap();
self.eval_op_assignment( self.eval_op_assignment(
mods, state, lib, op_info, op_pos, obj_ptr, root, new_val, mods, state, lib, op_info, op_pos, obj_ptr, root, new_val,
new_pos, new_pos,
)?; )?;
None return Ok((Dynamic::UNIT, true));
} }
Err(err) => match *err { // Can't index - try to call an index setter
// No index getter - try to call an index setter #[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_index"))] Err(err) if matches!(*err, EvalAltResult::ErrorIndexingType(_, _)) => {}
EvalAltResult::ErrorIndexingType(_, _) => Some(new_val.unwrap()), // Any other error
// Any other error - return Err(err) => return Err(err),
err => return err.into(),
},
};
if let Some(mut new_val) = _call_setter {
let val_type_name = target.type_name();
let ((_, val_pos), _) = new_val;
let hash_set = FnCallHashes::from_native(calc_fn_hash(
std::iter::empty(),
FN_IDX_SET,
3,
));
let args = &mut [target, &mut idx_val2, &mut (new_val.0).0];
self.exec_fn_call(
mods, state, lib, FN_IDX_SET, hash_set, args, is_ref, true,
val_pos, None, level,
)
.map_err(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.ends_with("]=") =>
{
EvalAltResult::ErrorIndexingType(
self.map_type_name(val_type_name).into(),
Position::NONE,
)
}
err => err,
})?;
} }
// Try to call index setter
let hash_set =
FnCallHashes::from_native(crate::calc_fn_hash(FN_IDX_SET, 3));
let args = &mut [target, &mut idx_val_for_setter, &mut new_val];
self.exec_fn_call(
mods, state, lib, FN_IDX_SET, hash_set, args, is_ref, true, new_pos,
None, level,
)?;
Ok((Dynamic::UNIT, true)) Ok((Dynamic::UNIT, true))
} }
// xxx[rhs] // xxx[rhs]
@ -1325,11 +1304,8 @@ impl Engine {
EvalAltResult::ErrorDotExpr(_, _) => { EvalAltResult::ErrorDotExpr(_, _) => {
let mut prop = name.into(); let mut prop = name.into();
let args = &mut [target, &mut prop, &mut new_val]; let args = &mut [target, &mut prop, &mut new_val];
let hash_set = FnCallHashes::from_native(crate::calc_fn_hash( let hash_set =
std::iter::empty(), FnCallHashes::from_native(crate::calc_fn_hash(FN_IDX_SET, 3));
FN_IDX_SET,
3,
));
self.exec_fn_call( self.exec_fn_call(
mods, state, lib, FN_IDX_SET, hash_set, args, is_ref, true, mods, state, lib, FN_IDX_SET, hash_set, args, is_ref, true,
*pos, None, level, *pos, None, level,
@ -1477,12 +1453,9 @@ impl Engine {
EvalAltResult::ErrorDotExpr(_, _) => { EvalAltResult::ErrorDotExpr(_, _) => {
let mut prop = name.into(); let mut prop = name.into();
let args = &mut [target.as_mut(), &mut prop, val]; let args = &mut [target.as_mut(), &mut prop, val];
let hash_set = let hash_set = FnCallHashes::from_native(
FnCallHashes::from_native(crate::calc_fn_hash( crate::calc_fn_hash(FN_IDX_SET, 3),
std::iter::empty(), );
FN_IDX_SET,
3,
));
self.exec_fn_call( self.exec_fn_call(
mods, state, lib, FN_IDX_SET, hash_set, args, mods, state, lib, FN_IDX_SET, hash_set, args,
is_ref, true, *pos, None, level, is_ref, true, *pos, None, level,
@ -1842,11 +1815,7 @@ impl Engine {
_ if indexers => { _ if indexers => {
let args = &mut [target, &mut idx]; let args = &mut [target, &mut idx];
let hash_get = FnCallHashes::from_native(crate::calc_fn_hash( let hash_get = FnCallHashes::from_native(crate::calc_fn_hash(FN_IDX_GET, 2));
std::iter::empty(),
FN_IDX_GET,
2,
));
self.exec_fn_call( self.exec_fn_call(
mods, state, lib, FN_IDX_GET, hash_get, args, true, true, idx_pos, None, level, mods, state, lib, FN_IDX_GET, hash_get, args, true, true, idx_pos, None, level,

View File

@ -24,7 +24,7 @@ use std::prelude::v1::*;
use std::{ use std::{
any::{type_name, TypeId}, any::{type_name, TypeId},
convert::TryFrom, convert::TryFrom,
iter::{empty, once}, iter::once,
mem, mem,
}; };
@ -653,7 +653,7 @@ impl Engine {
if num_params < 0 { if num_params < 0 {
Dynamic::FALSE Dynamic::FALSE
} else { } else {
let hash_script = calc_fn_hash(empty(), fn_name, num_params as usize); let hash_script = calc_fn_hash(fn_name, num_params as usize);
self.has_script_fn(Some(mods), state, lib, hash_script) self.has_script_fn(Some(mods), state, lib, hash_script)
.into() .into()
}, },
@ -911,7 +911,7 @@ impl Engine {
let fn_name = fn_ptr.fn_name(); let fn_name = fn_ptr.fn_name();
let args_len = call_args.len() + fn_ptr.curry().len(); let args_len = call_args.len() + fn_ptr.curry().len();
// Recalculate hashes // Recalculate hashes
let new_hash = FnCallHashes::from_script(calc_fn_hash(empty(), fn_name, args_len)); let new_hash = FnCallHashes::from_script(calc_fn_hash(fn_name, args_len));
// Arguments are passed as-is, adding the curried arguments // Arguments are passed as-is, adding the curried arguments
let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>(); let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>();
let mut args = curry let mut args = curry
@ -947,8 +947,8 @@ impl Engine {
let args_len = call_args.len() + fn_ptr.curry().len(); let args_len = call_args.len() + fn_ptr.curry().len();
// Recalculate hash // Recalculate hash
let new_hash = FnCallHashes::from_script_and_native( let new_hash = FnCallHashes::from_script_and_native(
calc_fn_hash(empty(), fn_name, args_len), calc_fn_hash(fn_name, args_len),
calc_fn_hash(empty(), fn_name, args_len + 1), calc_fn_hash(fn_name, args_len + 1),
); );
// Replace the first argument with the object pointer, adding the curried arguments // Replace the first argument with the object pointer, adding the curried arguments
let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>(); let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>();
@ -1021,8 +1021,8 @@ impl Engine {
}); });
// 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 = FnCallHashes::from_script_and_native( hash = FnCallHashes::from_script_and_native(
calc_fn_hash(empty(), fn_name, call_args.len()), calc_fn_hash(fn_name, call_args.len()),
calc_fn_hash(empty(), fn_name, call_args.len() + 1), calc_fn_hash(fn_name, call_args.len() + 1),
); );
} }
} }
@ -1107,9 +1107,9 @@ impl Engine {
// Recalculate hash // Recalculate hash
let args_len = total_args + curry.len(); let args_len = total_args + curry.len();
hashes = if !hashes.is_native_only() { hashes = if !hashes.is_native_only() {
FnCallHashes::from_script(calc_fn_hash(empty(), name, args_len)) FnCallHashes::from_script(calc_fn_hash(name, args_len))
} else { } else {
FnCallHashes::from_native(calc_fn_hash(empty(), name, args_len)) FnCallHashes::from_native(calc_fn_hash(name, args_len))
}; };
} }
// Handle Fn() // Handle Fn()
@ -1206,7 +1206,7 @@ impl Engine {
return Ok(if num_params < 0 { return Ok(if num_params < 0 {
Dynamic::FALSE Dynamic::FALSE
} else { } else {
let hash_script = calc_fn_hash(empty(), &fn_name, num_params as usize); let hash_script = calc_fn_hash(&fn_name, num_params as usize);
self.has_script_fn(Some(mods), state, lib, hash_script) self.has_script_fn(Some(mods), state, lib, hash_script)
.into() .into()
}); });

View File

@ -13,7 +13,7 @@ use std::prelude::v1::*;
use std::{ use std::{
convert::{TryFrom, TryInto}, convert::{TryFrom, TryInto},
fmt, fmt,
iter::{empty, once}, iter::once,
mem, mem,
}; };
@ -202,11 +202,11 @@ impl<'a> NativeCallContext<'a> {
let hash = if is_method { let hash = if is_method {
FnCallHashes::from_script_and_native( FnCallHashes::from_script_and_native(
calc_fn_hash(empty(), fn_name, args.len() - 1), calc_fn_hash(fn_name, args.len() - 1),
calc_fn_hash(empty(), fn_name, args.len()), calc_fn_hash(fn_name, args.len()),
) )
} else { } else {
FnCallHashes::from_script(calc_fn_hash(empty(), fn_name, args.len())) FnCallHashes::from_script(calc_fn_hash(fn_name, args.len()))
}; };
self.engine() self.engine()

View File

@ -169,7 +169,7 @@ pub use fn_native::Shared;
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
use fn_native::Locked; use fn_native::Locked;
pub(crate) use utils::{calc_fn_hash, calc_fn_params_hash, combine_hashes}; pub(crate) use utils::{calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes};
pub use rhai_codegen::*; pub use rhai_codegen::*;

View File

@ -7,8 +7,8 @@ use crate::fn_register::RegisterNativeFunction;
use crate::token::Token; use crate::token::Token;
use crate::utils::IdentifierBuilder; use crate::utils::IdentifierBuilder;
use crate::{ use crate::{
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, EvalAltResult, Identifier, calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes, Dynamic, EvalAltResult,
ImmutableString, NativeCallContext, Position, Shared, StaticVec, Identifier, ImmutableString, NativeCallContext, Position, Shared, StaticVec,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -116,7 +116,7 @@ fn calc_native_fn_hash<'a>(
fn_name: impl AsRef<str>, fn_name: impl AsRef<str>,
params: &[TypeId], params: &[TypeId],
) -> u64 { ) -> u64 {
let hash_script = calc_fn_hash(modules, fn_name, params.len()); let hash_script = calc_qualified_fn_hash(modules, fn_name, params.len());
let hash_params = calc_fn_params_hash(params.iter().cloned()); let hash_params = calc_fn_params_hash(params.iter().cloned());
combine_hashes(hash_script, hash_params) combine_hashes(hash_script, hash_params)
} }
@ -440,7 +440,7 @@ impl Module {
let value = Dynamic::from(value); let value = Dynamic::from(value);
if self.indexed { if self.indexed {
let hash_var = crate::calc_fn_hash(once(""), &ident, 0); let hash_var = crate::calc_qualified_fn_hash(once(""), &ident, 0);
self.all_variables.insert(hash_var, value.clone()); self.all_variables.insert(hash_var, value.clone());
} }
self.variables.insert(ident, value); self.variables.insert(ident, value);
@ -466,7 +466,7 @@ impl Module {
// None + function name + number of arguments. // None + function name + number of arguments.
let num_params = fn_def.params.len(); let num_params = fn_def.params.len();
let hash_script = crate::calc_fn_hash(empty(), &fn_def.name, num_params); let hash_script = crate::calc_fn_hash(&fn_def.name, num_params);
let mut param_names = fn_def.params.clone(); let mut param_names = fn_def.params.clone();
param_names.push("Dynamic".into()); param_names.push("Dynamic".into());
self.functions.insert( self.functions.insert(
@ -1491,7 +1491,7 @@ impl Module {
// Index all variables // Index all variables
module.variables.iter().for_each(|(var_name, value)| { module.variables.iter().for_each(|(var_name, value)| {
let hash_var = crate::calc_fn_hash(path.iter().map(|&v| v), var_name, 0); let hash_var = crate::calc_qualified_fn_hash(path.iter().map(|&v| v), var_name, 0);
variables.insert(hash_var, value.clone()); variables.insert(hash_var, value.clone());
}); });
@ -1521,8 +1521,11 @@ impl Module {
calc_native_fn_hash(path.iter().cloned(), f.name.as_str(), &f.param_types); calc_native_fn_hash(path.iter().cloned(), f.name.as_str(), &f.param_types);
functions.insert(hash_qualified_fn, f.func.clone()); functions.insert(hash_qualified_fn, f.func.clone());
} else if cfg!(not(feature = "no_function")) { } else if cfg!(not(feature = "no_function")) {
let hash_qualified_script = let hash_qualified_script = crate::calc_qualified_fn_hash(
crate::calc_fn_hash(path.iter().cloned(), f.name.as_str(), f.params); path.iter().cloned(),
f.name.as_str(),
f.params,
);
functions.insert(hash_qualified_script, f.func.clone()); functions.insert(hash_qualified_script, f.func.clone());
} }
}); });

View File

@ -15,7 +15,6 @@ use std::prelude::v1::*;
use std::{ use std::{
any::TypeId, any::TypeId,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
iter::empty,
mem, mem,
}; };
@ -147,7 +146,7 @@ fn call_fn_with_constant_arguments(
&mut Default::default(), &mut Default::default(),
state.lib, state.lib,
fn_name, fn_name,
calc_fn_hash(empty(), fn_name, arg_values.len()), calc_fn_hash(fn_name, arg_values.len()),
arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(), arg_values.iter_mut().collect::<StaticVec<_>>().as_mut(),
false, false,
false, false,

View File

@ -15,15 +15,14 @@ use crate::token::{
}; };
use crate::utils::{get_hasher, IdentifierBuilder}; use crate::utils::{get_hasher, IdentifierBuilder};
use crate::{ use crate::{
calc_fn_hash, Dynamic, Engine, FnPtr, Identifier, LexError, ParseError, ParseErrorType, calc_fn_hash, calc_qualified_fn_hash, Dynamic, Engine, FnPtr, Identifier, LexError, ParseError,
Position, Scope, Shared, StaticVec, AST, ParseErrorType, Position, Scope, Shared, StaticVec, AST,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
iter::empty,
num::{NonZeroU8, NonZeroUsize}, num::{NonZeroU8, NonZeroUsize},
}; };
@ -225,9 +224,9 @@ impl Expr {
Self::Variable(_, pos, x) if x.1.is_none() => { Self::Variable(_, pos, x) if x.1.is_none() => {
let ident = x.2; let ident = x.2;
let getter = state.get_identifier(crate::engine::make_getter(&ident)); let getter = state.get_identifier(crate::engine::make_getter(&ident));
let hash_get = calc_fn_hash(empty(), &getter, 1); let hash_get = calc_fn_hash(&getter, 1);
let setter = state.get_identifier(crate::engine::make_setter(&ident)); let setter = state.get_identifier(crate::engine::make_setter(&ident));
let hash_set = calc_fn_hash(empty(), &setter, 2); let hash_set = calc_fn_hash(&setter, 2);
Self::Property(Box::new(( Self::Property(Box::new((
(getter, hash_get), (getter, hash_get),
@ -334,9 +333,9 @@ fn parse_fn_call(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
modules.set_index(state.find_module(&modules[0].name)); modules.set_index(state.find_module(&modules[0].name));
calc_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, 0) calc_qualified_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, 0)
} else { } else {
calc_fn_hash(empty(), &id, 0) calc_fn_hash(&id, 0)
}; };
let hashes = if is_valid_identifier(id.chars()) { let hashes = if is_valid_identifier(id.chars()) {
@ -381,9 +380,9 @@ fn parse_fn_call(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
modules.set_index(state.find_module(&modules[0].name)); modules.set_index(state.find_module(&modules[0].name));
calc_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, args.len()) calc_qualified_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, args.len())
} else { } else {
calc_fn_hash(empty(), &id, args.len()) calc_fn_hash(&id, args.len())
}; };
let hashes = if is_valid_identifier(id.chars()) { let hashes = if is_valid_identifier(id.chars()) {
@ -1016,7 +1015,7 @@ fn parse_primary(
state.access_var(closure, *pos); state.access_var(closure, *pos);
}); });
let hash_script = calc_fn_hash(empty(), &func.name, func.params.len()); let hash_script = calc_fn_hash(&func.name, func.params.len());
lib.insert(hash_script, func.into()); lib.insert(hash_script, func.into());
expr expr
@ -1295,7 +1294,7 @@ fn parse_primary(
} }
.map(|x| match x.as_mut() { .map(|x| match x.as_mut() {
(_, Some((hash, namespace)), name) => { (_, Some((hash, namespace)), name) => {
*hash = calc_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0); *hash = calc_qualified_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0);
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
namespace.set_index(state.find_module(&namespace[0].name)); namespace.set_index(state.find_module(&namespace[0].name));
@ -1351,7 +1350,7 @@ fn parse_unary(
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier("-"), name: state.get_identifier("-"),
hashes: FnCallHashes::from_native(calc_fn_hash(empty(), "-", 1)), hashes: FnCallHashes::from_native(calc_fn_hash("-", 1)),
args, args,
..Default::default() ..Default::default()
}), }),
@ -1378,7 +1377,7 @@ fn parse_unary(
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier("+"), name: state.get_identifier("+"),
hashes: FnCallHashes::from_native(calc_fn_hash(empty(), "+", 1)), hashes: FnCallHashes::from_native(calc_fn_hash("+", 1)),
args, args,
..Default::default() ..Default::default()
}), }),
@ -1397,7 +1396,7 @@ fn parse_unary(
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier("!"), name: state.get_identifier("!"),
hashes: FnCallHashes::from_native(calc_fn_hash(empty(), "!", 1)), hashes: FnCallHashes::from_native(calc_fn_hash("!", 1)),
args, args,
..Default::default() ..Default::default()
}), }),
@ -1531,9 +1530,9 @@ fn make_dot_expr(
(lhs, Expr::Variable(_, var_pos, x)) if x.1.is_none() => { (lhs, Expr::Variable(_, var_pos, x)) if x.1.is_none() => {
let ident = x.2; let ident = x.2;
let getter = state.get_identifier(crate::engine::make_getter(&ident)); let getter = state.get_identifier(crate::engine::make_getter(&ident));
let hash_get = calc_fn_hash(empty(), &getter, 1); let hash_get = calc_fn_hash(&getter, 1);
let setter = state.get_identifier(crate::engine::make_setter(&ident)); let setter = state.get_identifier(crate::engine::make_setter(&ident));
let hash_set = calc_fn_hash(empty(), &setter, 2); let hash_set = calc_fn_hash(&setter, 2);
let rhs = Expr::Property(Box::new(( let rhs = Expr::Property(Box::new((
(getter, hash_get), (getter, hash_get),
@ -1566,8 +1565,8 @@ fn make_dot_expr(
Expr::FnCall(mut func, func_pos) => { Expr::FnCall(mut func, func_pos) => {
// Recalculate hash // Recalculate hash
func.hashes = FnCallHashes::from_script_and_native( func.hashes = FnCallHashes::from_script_and_native(
calc_fn_hash(empty(), &func.name, func.args_count()), calc_fn_hash(&func.name, func.args_count()),
calc_fn_hash(empty(), &func.name, func.args_count() + 1), calc_fn_hash(&func.name, func.args_count() + 1),
); );
let rhs = Expr::Dot( let rhs = Expr::Dot(
@ -1622,8 +1621,8 @@ fn make_dot_expr(
(lhs, Expr::FnCall(mut func, func_pos)) => { (lhs, Expr::FnCall(mut func, func_pos)) => {
// Recalculate hash // Recalculate hash
func.hashes = FnCallHashes::from_script_and_native( func.hashes = FnCallHashes::from_script_and_native(
calc_fn_hash(empty(), &func.name, func.args_count()), calc_fn_hash(&func.name, func.args_count()),
calc_fn_hash(empty(), &func.name, func.args_count() + 1), calc_fn_hash(&func.name, func.args_count() + 1),
); );
let rhs = Expr::FnCall(func, func_pos); let rhs = Expr::FnCall(func, func_pos);
Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos) Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos)
@ -1705,7 +1704,7 @@ fn parse_binary_op(
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
let op = op_token.syntax(); let op = op_token.syntax();
let hash = calc_fn_hash(empty(), &op, 2); let hash = calc_fn_hash(&op, 2);
let op_base = FnCallExpr { let op_base = FnCallExpr {
name: state.get_identifier(op.as_ref()), name: state.get_identifier(op.as_ref()),
@ -1773,7 +1772,7 @@ fn parse_binary_op(
args.shrink_to_fit(); args.shrink_to_fit();
// Convert into a call to `contains` // Convert into a call to `contains`
let hash = calc_fn_hash(empty(), OP_CONTAINS, 2); let hash = calc_fn_hash(OP_CONTAINS, 2);
Expr::FnCall( Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
hashes: FnCallHashes::from_script(hash), hashes: FnCallHashes::from_script(hash),
@ -1792,7 +1791,7 @@ fn parse_binary_op(
.get(s.as_str()) .get(s.as_str())
.map_or(false, Option::is_some) => .map_or(false, Option::is_some) =>
{ {
let hash = calc_fn_hash(empty(), &s, 2); let hash = calc_fn_hash(&s, 2);
Expr::FnCall( Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
@ -2580,7 +2579,7 @@ fn parse_stmt(
comments, comments,
)?; )?;
let hash = calc_fn_hash(empty(), &func.name, func.params.len()); let hash = calc_fn_hash(&func.name, func.params.len());
if lib.contains_key(&hash) { if lib.contains_key(&hash) {
return Err(PERR::FnDuplicatedDefinition( return Err(PERR::FnDuplicatedDefinition(
@ -2863,7 +2862,6 @@ fn make_curry_from_externals(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier(crate::engine::KEYWORD_FN_PTR_CURRY), name: state.get_identifier(crate::engine::KEYWORD_FN_PTR_CURRY),
hashes: FnCallHashes::from_native(calc_fn_hash( hashes: FnCallHashes::from_native(calc_fn_hash(
empty(),
crate::engine::KEYWORD_FN_PTR_CURRY, crate::engine::KEYWORD_FN_PTR_CURRY,
num_externals + 1, num_externals + 1,
)), )),

View File

@ -10,7 +10,7 @@ use std::{
cmp::Ordering, cmp::Ordering,
fmt, fmt,
hash::{BuildHasher, Hash, Hasher}, hash::{BuildHasher, Hash, Hasher},
iter::FromIterator, iter::{empty, FromIterator},
ops::{Add, AddAssign, Deref, Sub, SubAssign}, ops::{Add, AddAssign, Deref, Sub, SubAssign},
str::FromStr, str::FromStr,
}; };
@ -58,9 +58,8 @@ pub fn get_hasher() -> ahash::AHasher {
Default::default() Default::default()
} }
/// _(INTERNALS)_ Calculate a [`u64`] hash key from a namespace-qualified function name /// Calculate a [`u64`] hash key from a namespace-qualified function name
/// and the number of parameters, but no parameter types. /// and the number of parameters, but no parameter types.
/// Exported under the `internals` feature only.
/// ///
/// Module names are passed in via `&str` references from an iterator. /// Module names are passed in via `&str` references from an iterator.
/// Parameter types are passed in via [`TypeId`] values from an iterator. /// Parameter types are passed in via [`TypeId`] values from an iterator.
@ -68,8 +67,8 @@ pub fn get_hasher() -> ahash::AHasher {
/// # Note /// # Note
/// ///
/// The first module name is skipped. Hashing starts from the _second_ module in the chain. /// The first module name is skipped. Hashing starts from the _second_ module in the chain.
#[inline(always)] #[inline]
pub fn calc_fn_hash<'a>( pub fn calc_qualified_fn_hash<'a>(
modules: impl Iterator<Item = &'a str>, modules: impl Iterator<Item = &'a str>,
fn_name: impl AsRef<str>, fn_name: impl AsRef<str>,
num: usize, num: usize,
@ -88,11 +87,19 @@ pub fn calc_fn_hash<'a>(
s.finish() s.finish()
} }
/// _(INTERNALS)_ Calculate a [`u64`] hash key from a list of parameter types. /// Calculate a [`u64`] hash key from a non-namespace-qualified function name
/// Exported under the `internals` feature only. /// and the number of parameters, but no parameter types.
/// ///
/// Parameter types are passed in via [`TypeId`] values from an iterator. /// Parameter types are passed in via [`TypeId`] values from an iterator.
#[inline(always)] #[inline(always)]
pub fn calc_fn_hash(fn_name: impl AsRef<str>, num: usize) -> u64 {
calc_qualified_fn_hash(empty(), fn_name, num)
}
/// Calculate a [`u64`] hash key from a list of parameter types.
///
/// Parameter types are passed in via [`TypeId`] values from an iterator.
#[inline]
pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 { pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
let s = &mut get_hasher(); let s = &mut get_hasher();
let mut len = 0; let mut len = 0;