Add get_fn_metadata_list.

This commit is contained in:
Stephen Chung
2020-11-23 19:11:32 +08:00
parent 8d410dfc71
commit b43223a94f
6 changed files with 162 additions and 47 deletions

View File

@@ -97,11 +97,11 @@ impl Imports {
}
/// Get an iterator to this stack of imported modules in reverse order.
#[allow(dead_code)]
pub fn iter(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> + 'a {
self.0.iter().flat_map(|lib| {
lib.iter()
.rev()
.map(|(name, module)| (name.as_str(), module.clone()))
.map(|(name, module)| (name.clone(), module.clone()))
})
}
/// Get an iterator to this stack of imported modules in reverse order.

View File

@@ -1500,10 +1500,16 @@ impl Module {
)
}
/// Get an iterator to the sub-modules in the module.
#[inline(always)]
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
self.modules.iter().map(|(k, m)| (k.as_str(), m.clone()))
}
/// Get an iterator to the variables in the module.
#[inline(always)]
pub fn iter_var(&self) -> impl Iterator<Item = (&String, &Dynamic)> {
self.variables.iter()
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
self.variables.iter().map(|(k, v)| (k.as_str(), v))
}
/// Get an iterator to the functions in the module.

View File

@@ -1,5 +1,12 @@
use crate::module::SharedScriptFnDef;
use crate::plugin::*;
use crate::{def_package, FnPtr};
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"))]
use crate::{stdlib::collections::HashMap, Array, Map};
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
@@ -13,10 +20,111 @@ mod fn_ptr_functions {
}
#[cfg(not(feature = "no_function"))]
pub mod anonymous {
pub mod functions {
#[rhai_fn(name = "is_anonymous", get = "is_anonymous")]
pub fn is_anonymous(f: &mut FnPtr) -> bool {
f.is_anonymous()
}
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)
}
}
}
#[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(
dict: &HashMap<String, ImmutableString>,
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,
dict: &HashMap<String, ImmutableString>,
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
let mut dict = HashMap::<String, ImmutableString>::with_capacity(8);
dict.insert("namespace".into(), "namespace".into());
dict.insert("name".into(), "name".into());
dict.insert("access".into(), "access".into());
dict.insert("public".into(), "public".into());
dict.insert("private".into(), "private".into());
dict.insert("is_anonymous".into(), "is_anonymous".into());
dict.insert("params".into(), "params".into());
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
}

View File

@@ -4,34 +4,9 @@ use super::iter_basic::BasicIteratorPackage;
use super::logic::LogicPackage;
use super::string_basic::BasicStringPackage;
use crate::fn_native::{CallableFunction, FnCallArgs};
use crate::stdlib::{any::TypeId, boxed::Box, iter::empty};
use crate::{
calc_script_fn_hash, def_package, FnAccess, FnNamespace, ImmutableString, NativeCallContext,
INT,
};
use crate::def_package;
def_package!(crate:CorePackage:"_Core_ package containing basic facilities.", lib, {
#[cfg(not(feature = "no_function"))]
{
let f = |ctx: NativeCallContext, args: &mut FnCallArgs| {
let num_params = args[1].clone().cast::<INT>();
let fn_name = args[0].as_str().unwrap();
Ok(if num_params < 0 {
false.into()
} 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).into()
})
};
lib.set_fn("is_def_fn", FnNamespace::Global, FnAccess::Public,
Some(&["fn_name: &str", "num_params: INT"]),
&[TypeId::of::<ImmutableString>(), TypeId::of::<INT>()],
CallableFunction::from_method(Box::new(f)));
}
ArithmeticPackage::init(lib);
LogicPackage::init(lib);
BasicStringPackage::init(lib);