rhai/src/packages/fn_basic.rs

136 lines
4.0 KiB
Rust
Raw Normal View History

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-20 16:11:41 +02:00
#[export_module]
mod fn_ptr_functions {
#[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-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
}