quad_compat_rhai/packages/
fn_basic.rs

1use crate::plugin::*;
2use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
3#[cfg(feature = "no_std")]
4use std::prelude::v1::*;
5
6def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
7    lib.standard = true;
8
9    combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
10});
11
12#[export_module]
13mod fn_ptr_functions {
14    #[rhai_fn(name = "name", get = "name", pure)]
15    pub fn name(fn_ptr: &mut FnPtr) -> ImmutableString {
16        fn_ptr.fn_name_raw().into()
17    }
18
19    #[cfg(not(feature = "no_function"))]
20    #[rhai_fn(name = "is_anonymous", get = "is_anonymous", pure)]
21    pub fn is_anonymous(fn_ptr: &mut FnPtr) -> bool {
22        fn_ptr.is_anonymous()
23    }
24
25    #[cfg(not(feature = "no_function"))]
26    #[cfg(not(feature = "no_index"))]
27    #[cfg(not(feature = "no_object"))]
28    pub fn get_fn_metadata_list(ctx: NativeCallContext) -> crate::Array {
29        collect_fn_metadata(ctx)
30    }
31}
32
33#[cfg(not(feature = "no_function"))]
34#[cfg(not(feature = "no_index"))]
35#[cfg(not(feature = "no_object"))]
36fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
37    use crate::{ast::ScriptFnDef, Array, Identifier, Map};
38    use std::collections::BTreeSet;
39
40    // Create a metadata record for a function.
41    fn make_metadata(
42        dict: &BTreeSet<Identifier>,
43        namespace: Option<Identifier>,
44        f: &ScriptFnDef,
45    ) -> Map {
46        const DICT: &str = "key exists";
47
48        let mut map = Map::new();
49
50        if let Some(ns) = namespace {
51            map.insert(dict.get("namespace").expect(DICT).clone(), ns.into());
52        }
53        map.insert(dict.get("name").expect(DICT).clone(), f.name.clone().into());
54        map.insert(
55            dict.get("access").expect(DICT).clone(),
56            match f.access {
57                FnAccess::Public => dict.get("public").expect(DICT).clone(),
58                FnAccess::Private => dict.get("private").expect(DICT).clone(),
59            }
60            .into(),
61        );
62        map.insert(
63            dict.get("is_anonymous").expect(DICT).clone(),
64            f.name.starts_with(crate::engine::FN_ANONYMOUS).into(),
65        );
66        map.insert(
67            dict.get("params").expect(DICT).clone(),
68            f.params
69                .iter()
70                .cloned()
71                .map(Into::<Dynamic>::into)
72                .collect::<Array>()
73                .into(),
74        );
75
76        map
77    }
78
79    // Intern strings
80    let dict: BTreeSet<Identifier> = [
81        "namespace",
82        "name",
83        "access",
84        "public",
85        "private",
86        "is_anonymous",
87        "params",
88    ]
89    .iter()
90    .map(|&s| s.into())
91    .collect();
92
93    let mut _list = ctx.iter_namespaces().flat_map(Module::iter_script_fn).fold(
94        Array::new(),
95        |mut list, (_, _, _, _, f)| {
96            list.push(make_metadata(&dict, None, f).into());
97            list
98        },
99    );
100
101    #[cfg(not(feature = "no_module"))]
102    {
103        // Recursively scan modules for script-defined functions.
104        fn scan_module(
105            list: &mut Array,
106            dict: &BTreeSet<Identifier>,
107            namespace: Identifier,
108            module: &Module,
109        ) {
110            module.iter_script_fn().for_each(|(_, _, _, _, f)| {
111                list.push(make_metadata(dict, Some(namespace.clone()), f).into())
112            });
113            module.iter_sub_modules().for_each(|(ns, m)| {
114                let ns = format!(
115                    "{}{}{}",
116                    namespace,
117                    crate::tokenizer::Token::DoubleColon.literal_syntax(),
118                    ns
119                );
120                scan_module(list, dict, ns.into(), m.as_ref())
121            });
122        }
123
124        ctx.iter_imports_raw()
125            .for_each(|(ns, m)| scan_module(&mut _list, &dict, ns.clone(), m.as_ref()));
126    }
127
128    _list
129}