Split has_script_fn and has_native_fn.

This commit is contained in:
Stephen Chung 2021-03-08 18:40:23 +08:00
parent 57140cbeeb
commit fefa5a7dc7
2 changed files with 38 additions and 54 deletions

View File

@ -577,67 +577,37 @@ impl Engine {
result result
} }
// Has a system function a Rust-native override? // Does a scripted function exist?
#[inline(always)] #[inline(always)]
pub(crate) fn has_native_override( pub(crate) fn has_script_fn(
&self, &self,
mods: Option<&Imports>, mods: Option<&Imports>,
state: &mut State, state: &mut State,
lib: &[&Module], lib: &[&Module],
fn_name: &str, hash_script: u64,
arg_types: &[TypeId],
) -> bool {
let hash_script = calc_fn_hash(empty(), fn_name, arg_types.len());
let hash_params = calc_fn_params_hash(arg_types.iter().cloned());
let hash_fn = combine_hashes(hash_script, hash_params);
self.has_override(mods, state, lib, Some(hash_fn), None)
}
// Has a system function an override?
#[inline(always)]
pub(crate) fn has_override(
&self,
mods: Option<&Imports>,
state: &mut State,
lib: &[&Module],
hash_fn: Option<u64>,
hash_script: Option<u64>,
) -> bool { ) -> bool {
let cache = state.fn_resolution_cache_mut(); let cache = state.fn_resolution_cache_mut();
if hash_script.map_or(false, |hash| cache.contains_key(&hash)) if let Some(result) = cache.get(&hash_script).map(|v| v.is_some()) {
|| hash_fn.map_or(false, |hash| cache.contains_key(&hash)) return result;
{
return true;
} }
// First check script-defined functions // First check script-defined functions
if hash_script.map_or(false, |hash| lib.iter().any(|&m| m.contains_fn(hash, false))) let result = lib.iter().any(|&m| m.contains_fn(hash_script, false))
//|| hash_fn.map_or(false, |hash| lib.iter().any(|&m| m.contains_fn(hash, false)))
// Then check registered functions // Then check registered functions
|| hash_script.map_or(false, |hash| self.global_namespace.contains_fn(hash, false)) || self.global_namespace.contains_fn(hash_script, false)
|| hash_fn.map_or(false, |hash| self.global_namespace.contains_fn(hash, false))
// Then check packages // Then check packages
|| hash_script.map_or(false, |hash| self.global_modules.iter().any(|m| m.contains_fn(hash, false))) || self.global_modules.iter().any(|m| m.contains_fn(hash_script, false))
|| hash_fn.map_or(false, |hash| self.global_modules.iter().any(|m| m.contains_fn(hash, false)))
// Then check imported modules // Then check imported modules
|| hash_script.map_or(false, |hash| mods.map_or(false, |m| m.contains_fn(hash))) || mods.map_or(false, |m| m.contains_fn(hash_script))
|| hash_fn.map_or(false, |hash| mods.map_or(false, |m| m.contains_fn(hash)))
// Then check sub-modules // Then check sub-modules
|| hash_script.map_or(false, |hash| self.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash))) || self.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash_script));
|| hash_fn.map_or(false, |hash| self.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash)))
{ if !result {
true cache.insert(hash_script, None);
} else {
if let Some(hash_fn) = hash_fn {
cache.insert(hash_fn, None);
}
if let Some(hash_script) = hash_script {
cache.insert(hash_script, None);
}
false
} }
result
} }
/// Perform an actual function call, native Rust or scripted, taking care of special functions. /// Perform an actual function call, native Rust or scripted, taking care of special functions.
@ -689,7 +659,7 @@ impl Engine {
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(empty(), &fn_name, num_params as usize);
self.has_override(Some(mods), state, lib, None, Some(hash_script)) self.has_script_fn(Some(mods), state, lib, hash_script)
.into() .into()
}, },
false, false,
@ -1165,7 +1135,7 @@ impl Engine {
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(empty(), &fn_name, num_params as usize);
self.has_override(Some(mods), state, lib, None, Some(hash_script)) self.has_script_fn(Some(mods), state, lib, hash_script)
.into() .into()
}); });
} }

View File

@ -6,6 +6,7 @@ use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF}
use crate::fn_builtin::get_builtin_binary_op_fn; use crate::fn_builtin::get_builtin_binary_op_fn;
use crate::parser::map_dynamic_to_expr; use crate::parser::map_dynamic_to_expr;
use crate::stdlib::{ use crate::stdlib::{
any::TypeId,
boxed::Box, boxed::Box,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
iter::empty, iter::empty,
@ -15,8 +16,11 @@ use crate::stdlib::{
vec::Vec, vec::Vec,
}; };
use crate::token::is_valid_identifier; use crate::token::is_valid_identifier;
use crate::utils::{calc_fn_hash, get_hasher}; use crate::utils::get_hasher;
use crate::{Dynamic, Engine, Module, Position, Scope, StaticVec, AST}; use crate::{
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, Module, Position, Scope,
StaticVec, AST,
};
/// Level of optimization performed. /// Level of optimization performed.
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
@ -126,15 +130,25 @@ impl<'a> State<'a> {
} }
} }
// Has a system function a Rust-native override?
fn has_native_fn(state: &State, hash_script: u64, arg_types: &[TypeId]) -> bool {
let hash_params = calc_fn_params_hash(arg_types.iter().cloned());
let hash = combine_hashes(hash_script, hash_params);
// First check registered functions
state.engine.global_namespace.contains_fn(hash, false)
// Then check packages
|| state.engine.global_modules.iter().any(|m| m.contains_fn(hash, false))
// Then check sub-modules
|| state.engine.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash))
}
/// Call a registered function /// Call a registered function
fn call_fn_with_constant_arguments( fn call_fn_with_constant_arguments(
state: &State, state: &State,
fn_name: &str, fn_name: &str,
arg_values: &mut [Dynamic], arg_values: &mut [Dynamic],
) -> Option<Dynamic> { ) -> Option<Dynamic> {
// Search built-in's and external functions
let hash_native = calc_fn_hash(empty(), fn_name, arg_values.len());
state state
.engine .engine
.call_native_fn( .call_native_fn(
@ -142,7 +156,7 @@ fn call_fn_with_constant_arguments(
&mut Default::default(), &mut Default::default(),
state.lib, state.lib,
fn_name, fn_name,
hash_native, calc_fn_hash(empty(), 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,
@ -676,7 +690,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect(); let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect();
// Search for overloaded operators (can override built-in). // Search for overloaded operators (can override built-in).
if !state.engine.has_native_override(Some(&Default::default()), &mut Default::default(), state.lib, x.name.as_ref(), arg_types.as_ref()) { if !has_native_fn(state, x.hash.native_hash(), arg_types.as_ref()) {
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1]) if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
.and_then(|f| { .and_then(|f| {
let ctx = (state.engine, x.name.as_ref(), state.lib).into(); let ctx = (state.engine, x.name.as_ref(), state.lib).into();