Use zero for no hash.
This commit is contained in:
parent
6f6380ca3a
commit
54f78c5cd9
23
src/ast.rs
23
src/ast.rs
@ -1,6 +1,7 @@
|
|||||||
//! Module defining the AST (abstract syntax tree).
|
//! Module defining the AST (abstract syntax tree).
|
||||||
|
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
|
use crate::func::hashing::DEFAULT_HASH;
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::dynamic::Union;
|
use crate::types::dynamic::Union;
|
||||||
@ -1801,7 +1802,7 @@ impl OpAssignment<'_> {
|
|||||||
pub struct FnCallHashes {
|
pub struct FnCallHashes {
|
||||||
/// Pre-calculated hash for a script-defined function ([`None`] if native functions only).
|
/// Pre-calculated hash for a script-defined function ([`None`] if native functions only).
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub script: Option<u64>,
|
pub script: u64,
|
||||||
/// Pre-calculated hash for a native Rust function with no parameter types.
|
/// Pre-calculated hash for a native Rust function with no parameter types.
|
||||||
pub native: u64,
|
pub native: u64,
|
||||||
}
|
}
|
||||||
@ -1809,11 +1810,11 @@ pub struct FnCallHashes {
|
|||||||
impl fmt::Debug for FnCallHashes {
|
impl fmt::Debug for FnCallHashes {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if let Some(script) = self.script {
|
if self.script != 0 {
|
||||||
return if script == self.native {
|
return if self.script == self.native {
|
||||||
fmt::Debug::fmt(&self.native, f)
|
fmt::Debug::fmt(&self.native, f)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "({}, {})", script, self.native)
|
write!(f, "({}, {})", self.script, self.native)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1824,9 +1825,11 @@ impl fmt::Debug for FnCallHashes {
|
|||||||
impl From<u64> for FnCallHashes {
|
impl From<u64> for FnCallHashes {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(hash: u64) -> Self {
|
fn from(hash: u64) -> Self {
|
||||||
|
let hash = if hash == 0 { DEFAULT_HASH } else { hash };
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
script: Some(hash),
|
script: hash,
|
||||||
native: hash,
|
native: hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1839,8 +1842,8 @@ impl FnCallHashes {
|
|||||||
pub const fn from_native(hash: u64) -> Self {
|
pub const fn from_native(hash: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
script: None,
|
script: 0,
|
||||||
native: hash,
|
native: if hash == 0 { DEFAULT_HASH } else { hash },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Create a [`FnCallHashes`] with both native Rust and script function hashes.
|
/// Create a [`FnCallHashes`] with both native Rust and script function hashes.
|
||||||
@ -1849,8 +1852,8 @@ impl FnCallHashes {
|
|||||||
pub const fn from_all(#[cfg(not(feature = "no_function"))] script: u64, native: u64) -> Self {
|
pub const fn from_all(#[cfg(not(feature = "no_function"))] script: u64, native: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
script: Some(script),
|
script: if script == 0 { DEFAULT_HASH } else { script },
|
||||||
native,
|
native: if native == 0 { DEFAULT_HASH } else { native },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this [`FnCallHashes`] native Rust only?
|
/// Is this [`FnCallHashes`] native Rust only?
|
||||||
@ -1858,7 +1861,7 @@ impl FnCallHashes {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_native_only(&self) -> bool {
|
pub const fn is_native_only(&self) -> bool {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
return self.script.is_none();
|
return self.script == 0;
|
||||||
|
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
return true;
|
return true;
|
||||||
|
@ -177,6 +177,10 @@ impl Engine {
|
|||||||
allow_dynamic: bool,
|
allow_dynamic: bool,
|
||||||
is_op_assignment: bool,
|
is_op_assignment: bool,
|
||||||
) -> Option<&'s FnResolutionCacheEntry> {
|
) -> Option<&'s FnResolutionCacheEntry> {
|
||||||
|
if hash_script == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let fn_name = fn_name.as_ref();
|
let fn_name = fn_name.as_ref();
|
||||||
|
|
||||||
let mut hash = args.as_ref().map_or(hash_script, |args| {
|
let mut hash = args.as_ref().map_or(hash_script, |args| {
|
||||||
@ -562,13 +566,10 @@ impl Engine {
|
|||||||
|
|
||||||
// Scripted function call?
|
// Scripted function call?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
let hash_script = hashes.script;
|
if let Some(FnResolutionCacheEntry { func, source }) = self
|
||||||
|
.resolve_fn(mods, state, lib, fn_name, hashes.script, None, false, false)
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
if let Some(FnResolutionCacheEntry { func, source }) = hash_script.and_then(|hash| {
|
|
||||||
self.resolve_fn(mods, state, lib, fn_name, hash, None, false, false)
|
|
||||||
.cloned()
|
.cloned()
|
||||||
}) {
|
{
|
||||||
// Script function call
|
// Script function call
|
||||||
assert!(func.is_script());
|
assert!(func.is_script());
|
||||||
|
|
||||||
|
@ -8,7 +8,13 @@ use std::{
|
|||||||
iter::empty,
|
iter::empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A hasher that only takes one single [`u64`] and returns it as a hash key.
|
pub const DEFAULT_HASH: u64 = 42;
|
||||||
|
|
||||||
|
/// A hasher that only takes one single [`u64`] and returns it as a non-zero hash key.
|
||||||
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the value is zero, then it is mapped to `DEFAULT_HASH`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@ -29,6 +35,10 @@ impl Hasher for StraightHasher {
|
|||||||
key.copy_from_slice(bytes);
|
key.copy_from_slice(bytes);
|
||||||
|
|
||||||
self.0 = u64::from_ne_bytes(key);
|
self.0 = u64::from_ne_bytes(key);
|
||||||
|
|
||||||
|
if self.0 == 0 {
|
||||||
|
self.0 = DEFAULT_HASH
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +51,7 @@ impl BuildHasher for StraightHasherBuilder {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn build_hasher(&self) -> Self::Hasher {
|
fn build_hasher(&self) -> Self::Hasher {
|
||||||
StraightHasher(42)
|
StraightHasher(DEFAULT_HASH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,11 +62,15 @@ pub fn get_hasher() -> ahash::AHasher {
|
|||||||
ahash::AHasher::default()
|
ahash::AHasher::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a [`u64`] hash key from a namespace-qualified variable name.
|
/// Calculate a non-zero [`u64`] hash key from a namespace-qualified variable name.
|
||||||
///
|
///
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||||
|
///
|
||||||
/// # 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.
|
||||||
@ -76,15 +90,23 @@ pub fn calc_qualified_var_hash<'a>(
|
|||||||
.for_each(|m| m.as_ref().hash(s));
|
.for_each(|m| m.as_ref().hash(s));
|
||||||
len.hash(s);
|
len.hash(s);
|
||||||
var_name.as_ref().hash(s);
|
var_name.as_ref().hash(s);
|
||||||
s.finish()
|
|
||||||
|
match s.finish() {
|
||||||
|
0 => DEFAULT_HASH,
|
||||||
|
r => r,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a [`u64`] hash key from a namespace-qualified function name
|
/// Calculate a non-zero [`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.
|
||||||
///
|
///
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||||
|
///
|
||||||
/// # 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.
|
||||||
@ -106,22 +128,34 @@ pub fn calc_qualified_fn_hash(
|
|||||||
len.hash(s);
|
len.hash(s);
|
||||||
fn_name.as_ref().hash(s);
|
fn_name.as_ref().hash(s);
|
||||||
num.hash(s);
|
num.hash(s);
|
||||||
s.finish()
|
|
||||||
|
match s.finish() {
|
||||||
|
0 => DEFAULT_HASH,
|
||||||
|
r => r,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a [`u64`] hash key from a non-namespace-qualified function name
|
/// Calculate a non-zero [`u64`] hash key from a non-namespace-qualified function name
|
||||||
/// and the number of parameters, but no parameter types.
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn calc_fn_hash(fn_name: impl AsRef<str>, num: usize) -> u64 {
|
pub fn calc_fn_hash(fn_name: impl AsRef<str>, num: usize) -> u64 {
|
||||||
calc_qualified_fn_hash(empty::<&str>(), fn_name, num)
|
calc_qualified_fn_hash(empty::<&str>(), fn_name, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a [`u64`] hash key from a list of parameter types.
|
/// Calculate a non-zero [`u64`] hash key from a list of parameter types.
|
||||||
///
|
///
|
||||||
/// Parameter types are passed in via [`TypeId`] values from an iterator.
|
/// Parameter types are passed in via [`TypeId`] values from an iterator.
|
||||||
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
|
pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
|
||||||
@ -129,12 +163,23 @@ pub fn calc_fn_params_hash(params: impl Iterator<Item = TypeId>) -> u64 {
|
|||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
params.inspect(|_| len += 1).for_each(|t| t.hash(s));
|
params.inspect(|_| len += 1).for_each(|t| t.hash(s));
|
||||||
len.hash(s);
|
len.hash(s);
|
||||||
s.finish()
|
|
||||||
|
match s.finish() {
|
||||||
|
0 => DEFAULT_HASH,
|
||||||
|
r => r,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine two [`u64`] hashes by taking the XOR of them.
|
/// Combine two [`u64`] hashes by taking the XOR of them.
|
||||||
|
///
|
||||||
|
/// # Zeros
|
||||||
|
///
|
||||||
|
/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn combine_hashes(a: u64, b: u64) -> u64 {
|
pub const fn combine_hashes(a: u64, b: u64) -> u64 {
|
||||||
a ^ b
|
match a ^ b {
|
||||||
|
0 => DEFAULT_HASH,
|
||||||
|
r => r,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user