Eliminate script hashes under no_function.

This commit is contained in:
Stephen Chung 2021-11-16 13:42:46 +08:00
parent b178d7c367
commit e961ae23fd
5 changed files with 48 additions and 29 deletions

View File

@ -1771,6 +1771,7 @@ impl OpAssignment<'_> {
#[derive(Clone, Copy, Eq, PartialEq, Hash, Default)] #[derive(Clone, Copy, Eq, PartialEq, Hash, Default)]
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"))]
pub script: Option<u64>, pub script: Option<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,
@ -1778,16 +1779,28 @@ 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"))]
if let Some(script) = self.script { if let Some(script) = self.script {
if script == self.native { return if script == self.native {
fmt::Debug::fmt(&self.native, f) fmt::Debug::fmt(&self.native, f)
} else { } else {
write!(f, "({}, {})", script, self.native) write!(f, "({}, {})", script, self.native)
};
} }
} else {
write!(f, "{} (native only)", self.native) write!(f, "{} (native only)", self.native)
} }
} }
impl From<u64> for FnCallHashes {
#[inline(always)]
fn from(hash: u64) -> Self {
Self {
#[cfg(not(feature = "no_function"))]
script: Some(hash),
native: hash,
}
}
} }
impl FnCallHashes { impl FnCallHashes {
@ -1796,24 +1809,17 @@ impl FnCallHashes {
#[must_use] #[must_use]
pub const fn from_native(hash: u64) -> Self { pub const fn from_native(hash: u64) -> Self {
Self { Self {
#[cfg(not(feature = "no_function"))]
script: None, script: None,
native: hash, native: hash,
} }
} }
/// Create a [`FnCallHashes`] with both native Rust and script function hashes set to the same value.
#[inline(always)]
#[must_use]
pub const fn from_script(hash: u64) -> Self {
Self {
script: Some(hash),
native: hash,
}
}
/// Create a [`FnCallHashes`] with both native Rust and script function hashes. /// Create a [`FnCallHashes`] with both native Rust and script function hashes.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub const fn from_script_and_native(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"))]
script: Some(script), script: Some(script),
native, native,
} }
@ -1822,7 +1828,11 @@ impl FnCallHashes {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub const fn is_native_only(&self) -> bool { pub const fn is_native_only(&self) -> bool {
self.script.is_none() #[cfg(not(feature = "no_function"))]
return self.script.is_none();
#[cfg(feature = "no_function")]
return true;
} }
} }

View File

@ -671,7 +671,7 @@ impl Engine {
is_method_call: bool, is_method_call: bool,
pos: Position, pos: Position,
scope: Option<&mut Scope>, scope: Option<&mut Scope>,
_level: usize, level: usize,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
fn no_method_err(name: &str, pos: Position) -> Result<(Dynamic, bool), Box<EvalAltResult>> { fn no_method_err(name: &str, pos: Position) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
let msg = format!("'{0}' should not be called this way. Try {0}(...);", name); let msg = format!("'{0}' should not be called this way. Try {0}(...);", name);
@ -682,6 +682,8 @@ impl Engine {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
ensure_no_data_race(fn_name, args, is_ref_mut)?; ensure_no_data_race(fn_name, args, is_ref_mut)?;
let _scope = scope;
let _level = level;
let _is_method_call = is_method_call; let _is_method_call = is_method_call;
// These may be redirected from method style calls. // These may be redirected from method style calls.
@ -750,7 +752,7 @@ impl Engine {
} }
let mut empty_scope; let mut empty_scope;
let scope = if let Some(scope) = scope { let scope = if let Some(scope) = _scope {
scope scope
} else { } else {
empty_scope = Scope::new(); empty_scope = Scope::new();
@ -914,7 +916,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(fn_name, args_len)); let new_hash = calc_fn_hash(fn_name, args_len).into();
// Arguments are passed as-is, adding the curried arguments // Arguments are passed as-is, adding the curried arguments
let mut curry = StaticVec::with_capacity(fn_ptr.num_curried()); let mut curry = StaticVec::with_capacity(fn_ptr.num_curried());
curry.extend(fn_ptr.curry().iter().cloned()); curry.extend(fn_ptr.curry().iter().cloned());
@ -948,7 +950,8 @@ 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 hash // Recalculate hash
let new_hash = FnCallHashes::from_script_and_native( let new_hash = FnCallHashes::from_all(
#[cfg(not(feature = "no_function"))]
calc_fn_hash(fn_name, args_len), calc_fn_hash(fn_name, args_len),
calc_fn_hash(fn_name, args_len + 1), calc_fn_hash(fn_name, args_len + 1),
); );
@ -1019,7 +1022,8 @@ impl Engine {
call_args.insert_many(0, fn_ptr.curry().iter().cloned()); call_args.insert_many(0, fn_ptr.curry().iter().cloned());
} }
// 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_all(
#[cfg(not(feature = "no_function"))]
calc_fn_hash(fn_name, call_args.len()), calc_fn_hash(fn_name, call_args.len()),
calc_fn_hash(fn_name, call_args.len() + 1), calc_fn_hash(fn_name, call_args.len() + 1),
); );
@ -1120,7 +1124,7 @@ 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(name, args_len)) calc_fn_hash(name, args_len).into()
} else { } else {
FnCallHashes::from_native(calc_fn_hash(name, args_len)) FnCallHashes::from_native(calc_fn_hash(name, args_len))
}; };

View File

@ -239,12 +239,13 @@ impl<'a> NativeCallContext<'a> {
args: &mut [&mut Dynamic], args: &mut [&mut Dynamic],
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let hash = if is_method_call { let hash = if is_method_call {
FnCallHashes::from_script_and_native( FnCallHashes::from_all(
#[cfg(not(feature = "no_function"))]
calc_fn_hash(fn_name, args.len() - 1), calc_fn_hash(fn_name, args.len() - 1),
calc_fn_hash(fn_name, args.len()), calc_fn_hash(fn_name, args.len()),
) )
} else { } else {
FnCallHashes::from_script(calc_fn_hash(fn_name, args.len())) calc_fn_hash(fn_name, args.len()).into()
}; };
self.engine() self.engine()

View File

@ -494,7 +494,7 @@ fn parse_fn_call(
); );
let hashes = if is_valid_function_name(&id) { let hashes = if is_valid_function_name(&id) {
FnCallHashes::from_script(hash) hash.into()
} else { } else {
FnCallHashes::from_native(hash) FnCallHashes::from_native(hash)
}; };
@ -544,7 +544,7 @@ fn parse_fn_call(
); );
let hashes = if is_valid_function_name(&id) { let hashes = if is_valid_function_name(&id) {
FnCallHashes::from_script(hash) hash.into()
} else { } else {
FnCallHashes::from_native(hash) FnCallHashes::from_native(hash)
}; };
@ -1758,7 +1758,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_all(
#[cfg(not(feature = "no_function"))]
calc_fn_hash(&func.name, func.args.len()), calc_fn_hash(&func.name, func.args.len()),
calc_fn_hash(&func.name, func.args.len() + 1), calc_fn_hash(&func.name, func.args.len() + 1),
); );
@ -1808,10 +1809,12 @@ fn make_dot_expr(
// lhs.func(...) // lhs.func(...)
(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_all(
#[cfg(not(feature = "no_function"))]
calc_fn_hash(&func.name, func.args.len()), calc_fn_hash(&func.name, func.args.len()),
calc_fn_hash(&func.name, func.args.len() + 1), calc_fn_hash(&func.name, func.args.len() + 1),
); );
let rhs = Expr::FnCall(func, func_pos); let rhs = Expr::FnCall(func, func_pos);
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos) Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
} }
@ -1962,7 +1965,7 @@ fn parse_binary_op(
// Convert into a call to `contains` // Convert into a call to `contains`
FnCallExpr { FnCallExpr {
hashes: FnCallHashes::from_script(calc_fn_hash(OP_CONTAINS, 2)), hashes: calc_fn_hash(OP_CONTAINS, 2).into(),
args, args,
name: state.get_identifier(OP_CONTAINS), name: state.get_identifier(OP_CONTAINS),
..op_base ..op_base
@ -1981,7 +1984,7 @@ fn parse_binary_op(
FnCallExpr { FnCallExpr {
hashes: if is_valid_function_name(&s) { hashes: if is_valid_function_name(&s) {
FnCallHashes::from_script(hash) hash.into()
} else { } else {
FnCallHashes::from_native(hash) FnCallHashes::from_native(hash)
}, },

View File

@ -589,6 +589,7 @@ impl<'a> Scope<'a> {
/// ///
/// Panics if the range is out of bounds. /// Panics if the range is out of bounds.
#[inline] #[inline]
#[allow(dead_code)]
pub(crate) fn remove_range(&mut self, start: usize, len: usize) { pub(crate) fn remove_range(&mut self, start: usize, len: usize) {
self.values.drain(start..start + len).for_each(|_| {}); self.values.drain(start..start + len).for_each(|_| {});
self.names.drain(start..start + len).for_each(|_| {}); self.names.drain(start..start + len).for_each(|_| {});