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)]
pub struct FnCallHashes {
/// Pre-calculated hash for a script-defined function ([`None`] if native functions only).
#[cfg(not(feature = "no_function"))]
pub script: Option<u64>,
/// Pre-calculated hash for a native Rust function with no parameter types.
pub native: u64,
@ -1778,16 +1779,28 @@ pub struct FnCallHashes {
impl fmt::Debug for FnCallHashes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(not(feature = "no_function"))]
if let Some(script) = self.script {
if script == self.native {
return if script == self.native {
fmt::Debug::fmt(&self.native, f)
} else {
write!(f, "({}, {})", script, self.native)
};
}
} else {
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 {
@ -1796,24 +1809,17 @@ impl FnCallHashes {
#[must_use]
pub const fn from_native(hash: u64) -> Self {
Self {
#[cfg(not(feature = "no_function"))]
script: None,
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.
#[inline(always)]
#[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 {
#[cfg(not(feature = "no_function"))]
script: Some(script),
native,
}
@ -1822,7 +1828,11 @@ impl FnCallHashes {
#[inline(always)]
#[must_use]
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,
pos: Position,
scope: Option<&mut Scope>,
_level: usize,
level: usize,
) -> 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);
@ -682,6 +682,8 @@ impl Engine {
#[cfg(not(feature = "no_closure"))]
ensure_no_data_race(fn_name, args, is_ref_mut)?;
let _scope = scope;
let _level = level;
let _is_method_call = is_method_call;
// These may be redirected from method style calls.
@ -750,7 +752,7 @@ impl Engine {
}
let mut empty_scope;
let scope = if let Some(scope) = scope {
let scope = if let Some(scope) = _scope {
scope
} else {
empty_scope = Scope::new();
@ -914,7 +916,7 @@ impl Engine {
let fn_name = fn_ptr.fn_name();
let args_len = call_args.len() + fn_ptr.curry().len();
// 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
let mut curry = StaticVec::with_capacity(fn_ptr.num_curried());
curry.extend(fn_ptr.curry().iter().cloned());
@ -948,7 +950,8 @@ impl Engine {
let fn_name = fn_ptr.fn_name();
let args_len = call_args.len() + fn_ptr.curry().len();
// 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 + 1),
);
@ -1019,7 +1022,8 @@ impl Engine {
call_args.insert_many(0, fn_ptr.curry().iter().cloned());
}
// 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() + 1),
);
@ -1120,7 +1124,7 @@ impl Engine {
// Recalculate hash
let args_len = total_args + curry.len();
hashes = if !hashes.is_native_only() {
FnCallHashes::from_script(calc_fn_hash(name, args_len))
calc_fn_hash(name, args_len).into()
} else {
FnCallHashes::from_native(calc_fn_hash(name, args_len))
};

View File

@ -239,12 +239,13 @@ impl<'a> NativeCallContext<'a> {
args: &mut [&mut Dynamic],
) -> Result<Dynamic, Box<EvalAltResult>> {
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()),
)
} else {
FnCallHashes::from_script(calc_fn_hash(fn_name, args.len()))
calc_fn_hash(fn_name, args.len()).into()
};
self.engine()

View File

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

View File

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