2020-08-14 12:58:34 +02:00
|
|
|
use crate::plugin::*;
|
2020-11-23 12:11:32 +01:00
|
|
|
use crate::stdlib::iter::empty;
|
|
|
|
use crate::{calc_script_fn_hash, def_package, FnPtr, ImmutableString, NativeCallContext, INT};
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-11-23 13:26:28 +01:00
|
|
|
use crate::{module::SharedScriptFnDef, stdlib::collections::HashMap, Array, Map};
|
2020-08-14 12:58:34 +02:00
|
|
|
|
2020-06-25 12:07:57 +02:00
|
|
|
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
2020-09-13 16:12:11 +02:00
|
|
|
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
2020-06-25 12:07:57 +02:00
|
|
|
});
|
2020-08-16 17:41:59 +02:00
|
|
|
|
2020-08-20 16:11:41 +02:00
|
|
|
#[export_module]
|
|
|
|
mod fn_ptr_functions {
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "name", get = "name")]
|
2020-08-24 04:38:15 +02:00
|
|
|
pub fn name(f: &mut FnPtr) -> ImmutableString {
|
2020-08-20 16:11:41 +02:00
|
|
|
f.get_fn_name().clone()
|
|
|
|
}
|
2020-10-18 16:10:08 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-11-23 12:11:32 +01:00
|
|
|
pub mod functions {
|
2020-10-18 16:10:08 +02:00
|
|
|
#[rhai_fn(name = "is_anonymous", get = "is_anonymous")]
|
|
|
|
pub fn is_anonymous(f: &mut FnPtr) -> bool {
|
|
|
|
f.is_anonymous()
|
|
|
|
}
|
2020-11-23 12:11:32 +01:00
|
|
|
|
|
|
|
pub fn is_def_fn(ctx: NativeCallContext, fn_name: &str, num_params: INT) -> bool {
|
|
|
|
if num_params < 0 {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
let hash_script = calc_script_fn_hash(empty(), fn_name, num_params as usize);
|
|
|
|
ctx.engine()
|
|
|
|
.has_override(ctx.mods, ctx.lib, 0, hash_script, true)
|
|
|
|
}
|
|
|
|
}
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
2020-11-23 12:11:32 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
pub mod functions_and_maps {
|
|
|
|
pub fn get_fn_metadata_list(ctx: NativeCallContext) -> Array {
|
|
|
|
collect_fn_metadata(ctx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
fn collect_fn_metadata(ctx: NativeCallContext) -> Array {
|
|
|
|
// Create a metadata record for a function.
|
|
|
|
fn make_metadata(
|
2020-11-23 14:12:57 +01:00
|
|
|
dict: &HashMap<&str, ImmutableString>,
|
2020-11-23 12:11:32 +01:00
|
|
|
namespace: Option<ImmutableString>,
|
|
|
|
f: SharedScriptFnDef,
|
|
|
|
) -> Map {
|
|
|
|
let mut map = Map::with_capacity(6);
|
|
|
|
|
|
|
|
if let Some(ns) = namespace {
|
|
|
|
map.insert(dict["namespace"].clone(), ns.into());
|
|
|
|
}
|
|
|
|
map.insert(dict["name"].clone(), f.name.clone().into());
|
|
|
|
map.insert(
|
|
|
|
dict["access"].clone(),
|
|
|
|
match f.access {
|
|
|
|
FnAccess::Public => dict["public"].clone(),
|
|
|
|
FnAccess::Private => dict["private"].clone(),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
map.insert(
|
|
|
|
dict["is_anonymous"].clone(),
|
|
|
|
f.name.starts_with(crate::engine::FN_ANONYMOUS).into(),
|
|
|
|
);
|
|
|
|
map.insert(
|
|
|
|
dict["params"].clone(),
|
|
|
|
f.params
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.map(Into::<Dynamic>::into)
|
|
|
|
.collect::<Array>()
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
|
|
|
|
map.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recursively scan modules for script-defined functions.
|
|
|
|
fn scan_module(
|
|
|
|
list: &mut Array,
|
2020-11-23 14:12:57 +01:00
|
|
|
dict: &HashMap<&str, ImmutableString>,
|
2020-11-23 12:11:32 +01:00
|
|
|
namespace: ImmutableString,
|
|
|
|
module: &Module,
|
|
|
|
) {
|
|
|
|
module.iter_script_fn().for_each(|(_, _, _, _, f)| {
|
|
|
|
list.push(make_metadata(dict, Some(namespace.clone()), f).into())
|
|
|
|
});
|
|
|
|
module.iter_sub_modules().for_each(|(ns, m)| {
|
|
|
|
let ns: ImmutableString = format!("{}::{}", namespace, ns).into();
|
|
|
|
scan_module(list, dict, ns, m.as_ref())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Intern strings
|
2020-11-23 14:12:57 +01:00
|
|
|
let mut dict = HashMap::<&str, ImmutableString>::with_capacity(8);
|
|
|
|
[
|
|
|
|
"namespace",
|
|
|
|
"name",
|
|
|
|
"access",
|
|
|
|
"public",
|
|
|
|
"private",
|
|
|
|
"is_anonymous",
|
|
|
|
"params",
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.for_each(|&s| {
|
|
|
|
dict.insert(s, s.into());
|
|
|
|
});
|
2020-11-23 12:11:32 +01:00
|
|
|
|
|
|
|
let mut list: Array = Default::default();
|
|
|
|
|
|
|
|
ctx.lib
|
|
|
|
.iter()
|
|
|
|
.flat_map(|m| m.iter_script_fn())
|
|
|
|
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into()));
|
|
|
|
|
|
|
|
if let Some(mods) = ctx.mods {
|
|
|
|
mods.iter()
|
|
|
|
.for_each(|(ns, m)| scan_module(&mut list, &dict, ns, m.as_ref()));
|
|
|
|
}
|
|
|
|
|
|
|
|
list
|
2020-08-16 17:41:59 +02:00
|
|
|
}
|