Streamline hashing function.
This commit is contained in:
parent
85a5aa14b3
commit
1545b602a7
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
});
|
});
|
||||||
|
@ -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()
|
||||||
|
@ -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::*;
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
)),
|
)),
|
||||||
|
21
src/utils.rs
21
src/utils.rs
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user