2020-05-05 12:24:13 +08:00
|
|
|
//! Module defining external-loaded modules for Rhai.
|
|
|
|
|
2020-12-22 16:45:56 +08:00
|
|
|
use crate::ast::{FnAccess, Ident};
|
2021-11-13 22:36:23 +08:00
|
|
|
use crate::func::{
|
2021-11-16 12:26:37 +08:00
|
|
|
shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction,
|
|
|
|
SendSync,
|
2021-11-13 22:36:23 +08:00
|
|
|
};
|
|
|
|
use crate::tokenizer::Token;
|
|
|
|
use crate::types::dynamic::Variant;
|
2021-04-17 15:15:54 +08:00
|
|
|
use crate::{
|
2021-12-25 23:49:14 +08:00
|
|
|
calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes, Dynamic, Identifier,
|
|
|
|
ImmutableString, NativeCallContext, RhaiResultOf, Shared, StaticVec,
|
2021-04-17 15:15:54 +08:00
|
|
|
};
|
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
|
|
|
use std::{
|
2020-05-06 16:09:44 +08:00
|
|
|
any::TypeId,
|
2022-01-13 19:07:56 +08:00
|
|
|
cmp::Ordering,
|
2021-04-06 23:18:41 +08:00
|
|
|
collections::{BTreeMap, BTreeSet},
|
|
|
|
fmt,
|
2021-04-17 22:19:48 +08:00
|
|
|
iter::{empty, once},
|
2020-05-08 22:38:56 +08:00
|
|
|
num::NonZeroUsize,
|
2020-10-07 15:40:36 +08:00
|
|
|
ops::{Add, AddAssign, Deref, DerefMut},
|
2020-11-16 23:10:14 +08:00
|
|
|
};
|
|
|
|
|
2020-11-17 12:23:53 +08:00
|
|
|
/// A type representing the namespace of a function.
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
|
|
|
pub enum FnNamespace {
|
2020-12-26 13:05:57 +08:00
|
|
|
/// Expose to global namespace.
|
2020-11-17 12:23:53 +08:00
|
|
|
Global,
|
2020-12-26 13:05:57 +08:00
|
|
|
/// Module namespace only.
|
2020-11-17 12:23:53 +08:00
|
|
|
Internal,
|
|
|
|
}
|
|
|
|
|
2022-01-13 19:07:56 +08:00
|
|
|
/// A type containing all metadata for a registered function.
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
|
|
|
pub struct FnMetadata {
|
2020-11-17 12:23:53 +08:00
|
|
|
/// Function namespace.
|
|
|
|
pub namespace: FnNamespace,
|
2020-11-04 14:37:46 +08:00
|
|
|
/// Function access mode.
|
|
|
|
pub access: FnAccess,
|
|
|
|
/// Function name.
|
2021-03-29 11:36:02 +08:00
|
|
|
pub name: Identifier,
|
2020-11-04 14:37:46 +08:00
|
|
|
/// Number of parameters.
|
|
|
|
pub params: usize,
|
2021-12-21 13:21:29 +08:00
|
|
|
/// Parameter names and types (if available).
|
2021-03-24 19:27:38 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-13 19:07:56 +08:00
|
|
|
pub params_info: StaticVec<Identifier>,
|
2021-12-21 13:21:29 +08:00
|
|
|
/// Return type name.
|
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-13 19:07:56 +08:00
|
|
|
pub return_type: Identifier,
|
2021-12-21 16:14:07 +08:00
|
|
|
/// Comments.
|
|
|
|
#[cfg(feature = "metadata")]
|
2021-12-21 22:16:03 +08:00
|
|
|
pub comments: Option<Box<[Box<str>]>>,
|
2020-11-22 17:21:34 +08:00
|
|
|
}
|
|
|
|
|
2022-01-13 19:07:56 +08:00
|
|
|
impl PartialOrd for FnMetadata {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for FnMetadata {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
match self.name.cmp(&other.name) {
|
2022-01-13 21:01:56 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-13 19:07:56 +08:00
|
|
|
Ordering::Equal => match self.params.cmp(&other.params) {
|
|
|
|
Ordering::Equal => self.params_info.cmp(&other.params_info),
|
|
|
|
cmp => cmp,
|
|
|
|
},
|
2022-01-13 21:01:56 +08:00
|
|
|
#[cfg(not(feature = "metadata"))]
|
|
|
|
Ordering::Equal => self.params.cmp(&other.params),
|
2022-01-13 19:07:56 +08:00
|
|
|
cmp => cmp,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A type containing a single registered function.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct FuncInfo {
|
|
|
|
/// Function instance.
|
|
|
|
pub func: Shared<CallableFunction>,
|
|
|
|
/// Parameter types (if applicable).
|
|
|
|
pub param_types: StaticVec<TypeId>,
|
|
|
|
/// Function metadata.
|
|
|
|
pub metadata: FnMetadata,
|
|
|
|
}
|
|
|
|
|
2020-11-22 17:21:34 +08:00
|
|
|
impl FuncInfo {
|
2022-01-13 22:51:10 +08:00
|
|
|
/// Format a return type to be display-friendly.
|
|
|
|
///
|
|
|
|
/// `()` is cleared.
|
|
|
|
/// [`RhaiResult`][crate::RhaiResult] and [`RhaiResultOf<T>`] are expanded.
|
2022-01-14 21:49:38 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-17 21:51:04 +08:00
|
|
|
pub fn format_type(typ: &str, is_return_type: bool) -> std::borrow::Cow<str> {
|
2022-01-13 22:51:10 +08:00
|
|
|
const RHAI_RESULT_TYPE: &str = "RhaiResult";
|
|
|
|
const RHAI_RESULT_TYPE_EXPAND: &str = "Result<Dynamic, Box<EvalAltResult>>";
|
|
|
|
const RHAI_RESULT_OF_TYPE: &str = "RhaiResultOf<";
|
|
|
|
const RHAI_RESULT_OF_TYPE_EXPAND: &str = "Result<{}, Box<EvalAltResult>>";
|
2022-01-17 21:51:04 +08:00
|
|
|
const RHAI_RANGE: &str = "ExclusiveRange";
|
|
|
|
const RHAI_RANGE_TYPE: &str = "Range<";
|
|
|
|
const RHAI_RANGE_EXPAND: &str = "Range<{}>";
|
|
|
|
const RHAI_INCLUSIVE_RANGE: &str = "InclusiveRange";
|
|
|
|
const RHAI_INCLUSIVE_RANGE_TYPE: &str = "RangeInclusive<";
|
|
|
|
const RHAI_INCLUSIVE_RANGE_EXPAND: &str = "RangeInclusive<{}>";
|
|
|
|
|
|
|
|
let typ = typ.trim();
|
|
|
|
|
|
|
|
if typ.starts_with("rhai::") {
|
|
|
|
return Self::format_type(&typ[6..], is_return_type);
|
|
|
|
} else if typ.starts_with("&mut ") {
|
|
|
|
let x = &typ[5..];
|
|
|
|
let r = Self::format_type(x, false);
|
|
|
|
return if r == x {
|
|
|
|
typ.into()
|
|
|
|
} else {
|
|
|
|
format!("&mut {}", r).into()
|
|
|
|
};
|
|
|
|
}
|
2022-01-13 22:51:10 +08:00
|
|
|
|
|
|
|
match typ {
|
2022-01-17 21:51:04 +08:00
|
|
|
"" | "()" if is_return_type => "".into(),
|
|
|
|
"INT" => std::any::type_name::<crate::INT>().into(),
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
"FLOAT" => std::any::type_name::<crate::FLOAT>().into(),
|
|
|
|
RHAI_RANGE => RHAI_RANGE_EXPAND
|
|
|
|
.replace("{}", std::any::type_name::<crate::INT>())
|
|
|
|
.into(),
|
|
|
|
RHAI_INCLUSIVE_RANGE => RHAI_INCLUSIVE_RANGE_EXPAND
|
|
|
|
.replace("{}", std::any::type_name::<crate::INT>())
|
|
|
|
.into(),
|
2022-01-13 22:51:10 +08:00
|
|
|
RHAI_RESULT_TYPE => RHAI_RESULT_TYPE_EXPAND.into(),
|
2022-01-17 21:51:04 +08:00
|
|
|
ty if ty.starts_with(RHAI_RANGE_TYPE) && ty.ends_with('>') => {
|
|
|
|
let inner = &ty[RHAI_RANGE_TYPE.len()..ty.len() - 1];
|
|
|
|
RHAI_RANGE_EXPAND
|
|
|
|
.replace("{}", Self::format_type(inner, false).trim())
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
ty if ty.starts_with(RHAI_INCLUSIVE_RANGE_TYPE) && ty.ends_with('>') => {
|
|
|
|
let inner = &ty[RHAI_INCLUSIVE_RANGE_TYPE.len()..ty.len() - 1];
|
|
|
|
RHAI_INCLUSIVE_RANGE_EXPAND
|
|
|
|
.replace("{}", Self::format_type(inner, false).trim())
|
|
|
|
.into()
|
|
|
|
}
|
2022-01-17 07:50:29 +08:00
|
|
|
ty if ty.starts_with(RHAI_RESULT_OF_TYPE) && ty.ends_with('>') => {
|
2022-01-17 21:51:04 +08:00
|
|
|
let inner = &ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1];
|
2022-01-13 22:51:10 +08:00
|
|
|
RHAI_RESULT_OF_TYPE_EXPAND
|
2022-01-17 21:51:04 +08:00
|
|
|
.replace("{}", Self::format_type(inner, false).trim())
|
2022-01-13 22:51:10 +08:00
|
|
|
.into()
|
|
|
|
}
|
|
|
|
ty => ty.into(),
|
|
|
|
}
|
|
|
|
}
|
2022-01-24 17:04:40 +08:00
|
|
|
/// _(metadata)_ Generate a signature of the function.
|
2021-04-02 12:34:39 +08:00
|
|
|
/// Exported under the `metadata` feature only.
|
2021-03-24 19:27:38 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-11-22 17:21:34 +08:00
|
|
|
pub fn gen_signature(&self) -> String {
|
2022-01-13 19:07:56 +08:00
|
|
|
let mut sig = format!("{}(", self.metadata.name);
|
2020-11-22 17:21:34 +08:00
|
|
|
|
2022-01-17 21:51:04 +08:00
|
|
|
let return_type = Self::format_type(&self.metadata.return_type, true);
|
2022-01-13 22:51:10 +08:00
|
|
|
|
2022-01-13 19:07:56 +08:00
|
|
|
if !self.metadata.params_info.is_empty() {
|
2021-12-21 13:21:29 +08:00
|
|
|
let params: StaticVec<_> = self
|
2022-01-13 19:07:56 +08:00
|
|
|
.metadata
|
|
|
|
.params_info
|
2021-12-21 13:21:29 +08:00
|
|
|
.iter()
|
2022-01-17 21:51:04 +08:00
|
|
|
.map(|s| {
|
|
|
|
let mut seg = s.splitn(2, ':');
|
|
|
|
let name = match seg.next().unwrap().trim() {
|
|
|
|
"" => "_",
|
|
|
|
s => s,
|
|
|
|
};
|
|
|
|
let result: std::borrow::Cow<str> = match seg.next() {
|
|
|
|
Some(typ) => {
|
|
|
|
format!("{}: {}", name, FuncInfo::format_type(typ, false)).into()
|
|
|
|
}
|
|
|
|
None => name.into(),
|
|
|
|
};
|
|
|
|
result
|
|
|
|
})
|
2021-12-21 13:21:29 +08:00
|
|
|
.collect();
|
2020-11-22 17:21:34 +08:00
|
|
|
sig.push_str(¶ms.join(", "));
|
2022-01-13 22:51:10 +08:00
|
|
|
sig.push(')');
|
2020-11-22 17:21:34 +08:00
|
|
|
} else {
|
2022-01-13 19:07:56 +08:00
|
|
|
for x in 0..self.metadata.params {
|
2021-07-26 22:22:27 +08:00
|
|
|
sig.push('_');
|
2022-01-13 19:07:56 +08:00
|
|
|
if x < self.metadata.params - 1 {
|
2020-11-22 17:21:34 +08:00
|
|
|
sig.push_str(", ");
|
|
|
|
}
|
|
|
|
}
|
2022-01-13 22:51:10 +08:00
|
|
|
sig.push(')');
|
2022-01-17 23:15:22 +08:00
|
|
|
}
|
2022-01-13 22:51:10 +08:00
|
|
|
|
2022-01-17 23:15:22 +08:00
|
|
|
if !self.func.is_script() && !return_type.is_empty() {
|
|
|
|
sig.push_str(" -> ");
|
|
|
|
sig.push_str(&return_type);
|
2020-11-22 17:21:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
sig
|
|
|
|
}
|
2020-11-04 14:37:46 +08:00
|
|
|
}
|
2020-09-25 18:07:39 +08:00
|
|
|
|
2021-12-06 10:34:13 +08:00
|
|
|
/// _(internals)_ Calculate a non-zero [`u64`] hash key from a namespace-qualified function name and parameter types.
|
2021-03-08 15:30:32 +08:00
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// Module names are passed in via `&str` references from an iterator.
|
|
|
|
/// Parameter types are passed in via [`TypeId`] values from an iterator.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2022-01-04 15:22:48 +08:00
|
|
|
pub fn calc_native_fn_hash<'a>(
|
|
|
|
modules: impl Iterator<Item = &'a str>,
|
|
|
|
fn_name: &str,
|
2021-03-08 15:30:32 +08:00
|
|
|
params: &[TypeId],
|
|
|
|
) -> u64 {
|
2022-01-04 15:22:48 +08:00
|
|
|
let hash_script = calc_qualified_fn_hash(modules, fn_name, params.len());
|
2021-03-08 15:30:32 +08:00
|
|
|
let hash_params = calc_fn_params_hash(params.iter().cloned());
|
|
|
|
combine_hashes(hash_script, hash_params)
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:26:50 +08:00
|
|
|
/// A module which may contain variables, sub-modules, external Rust functions,
|
|
|
|
/// and/or script-defined functions.
|
2020-11-15 12:07:35 +08:00
|
|
|
#[derive(Clone)]
|
2020-05-05 15:00:10 +08:00
|
|
|
pub struct Module {
|
2020-12-21 22:04:46 +08:00
|
|
|
/// ID identifying the module.
|
2022-01-01 17:20:00 +08:00
|
|
|
/// No ID if string is empty.
|
|
|
|
id: Identifier,
|
2021-04-17 18:40:16 +08:00
|
|
|
/// Is this module internal?
|
2021-05-08 22:59:33 +08:00
|
|
|
pub(crate) internal: bool,
|
2021-11-05 23:22:05 +08:00
|
|
|
/// Is this module part of a standard library?
|
|
|
|
pub(crate) standard: bool,
|
2020-05-05 15:00:10 +08:00
|
|
|
/// Sub-modules.
|
2021-03-29 11:36:02 +08:00
|
|
|
modules: BTreeMap<Identifier, Shared<Module>>,
|
2021-01-02 23:30:10 +08:00
|
|
|
/// [`Module`] variables.
|
2021-03-29 11:36:02 +08:00
|
|
|
variables: BTreeMap<Identifier, Dynamic>,
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
2021-03-23 12:13:53 +08:00
|
|
|
all_variables: BTreeMap<u64, Dynamic>,
|
2020-05-05 15:00:10 +08:00
|
|
|
/// External Rust functions.
|
2021-03-23 12:13:53 +08:00
|
|
|
functions: BTreeMap<u64, Box<FuncInfo>>,
|
2020-11-16 14:07:48 +08:00
|
|
|
/// Flattened collection of all external Rust functions, native or scripted.
|
2020-05-19 19:03:06 +08:00
|
|
|
/// including those in sub-modules.
|
2021-05-03 13:45:41 +08:00
|
|
|
all_functions: BTreeMap<u64, Shared<CallableFunction>>,
|
2020-11-15 12:07:35 +08:00
|
|
|
/// Iterator functions, keyed by the type producing the iterator.
|
2022-01-27 23:55:32 +08:00
|
|
|
type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
|
2020-11-16 14:07:48 +08:00
|
|
|
/// Flattened collection of iterator functions, including those in sub-modules.
|
2022-01-27 23:55:32 +08:00
|
|
|
all_type_iterators: BTreeMap<TypeId, Shared<IteratorFn>>,
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Is the [`Module`] indexed?
|
2020-06-27 23:56:24 +08:00
|
|
|
indexed: bool,
|
2021-03-05 20:07:35 +08:00
|
|
|
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
|
|
|
contains_indexed_global_functions: bool,
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2020-11-15 12:07:35 +08:00
|
|
|
impl Default for Module {
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2020-11-15 12:07:35 +08:00
|
|
|
fn default() -> Self {
|
2021-05-18 12:24:11 +08:00
|
|
|
Self::new()
|
2020-11-15 12:07:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:00:10 +08:00
|
|
|
impl fmt::Debug for Module {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-06 23:18:41 +08:00
|
|
|
let mut d = f.debug_struct("Module");
|
|
|
|
|
2022-01-01 17:20:00 +08:00
|
|
|
if !self.id.is_empty() {
|
|
|
|
d.field("id", &self.id);
|
|
|
|
}
|
2021-04-06 23:18:41 +08:00
|
|
|
if !self.modules.is_empty() {
|
|
|
|
d.field(
|
|
|
|
"modules",
|
|
|
|
&self
|
|
|
|
.modules
|
|
|
|
.keys()
|
|
|
|
.map(|m| m.as_str())
|
|
|
|
.collect::<BTreeSet<_>>(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if !self.variables.is_empty() {
|
|
|
|
d.field("vars", &self.variables);
|
|
|
|
}
|
|
|
|
if !self.functions.is_empty() {
|
|
|
|
d.field(
|
|
|
|
"functions",
|
|
|
|
&self
|
2021-12-06 11:12:54 +08:00
|
|
|
.iter_fn()
|
2021-04-20 19:19:35 +08:00
|
|
|
.map(|f| f.func.to_string())
|
2021-04-06 23:18:41 +08:00
|
|
|
.collect::<BTreeSet<_>>(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
d.finish()
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 23:09:33 +08:00
|
|
|
impl<M: AsRef<Module>> Add<M> for &Module {
|
|
|
|
type Output = Module;
|
|
|
|
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-01-11 23:09:33 +08:00
|
|
|
fn add(self, rhs: M) -> Self::Output {
|
|
|
|
let mut module = self.clone();
|
|
|
|
module.merge(rhs.as_ref());
|
|
|
|
module
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: AsRef<Module>> Add<M> for Module {
|
|
|
|
type Output = Self;
|
|
|
|
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-01-11 23:09:33 +08:00
|
|
|
fn add(mut self, rhs: M) -> Self::Output {
|
|
|
|
self.merge(rhs.as_ref());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<M: Into<Module>> AddAssign<M> for Module {
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-01-11 23:09:33 +08:00
|
|
|
fn add_assign(&mut self, rhs: M) {
|
|
|
|
self.combine(rhs.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 12:24:13 +08:00
|
|
|
impl Module {
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Create a new [`Module`].
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_var("answer", 42_i64);
|
2021-08-26 23:58:41 +08:00
|
|
|
/// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 12:24:13 +08:00
|
|
|
pub fn new() -> Self {
|
2021-05-18 12:24:11 +08:00
|
|
|
Self {
|
2022-01-01 17:20:00 +08:00
|
|
|
id: Identifier::new_const(),
|
2021-05-18 12:24:11 +08:00
|
|
|
internal: false,
|
2021-11-05 23:22:05 +08:00
|
|
|
standard: false,
|
2021-11-07 18:12:37 +08:00
|
|
|
modules: BTreeMap::new(),
|
|
|
|
variables: BTreeMap::new(),
|
|
|
|
all_variables: BTreeMap::new(),
|
|
|
|
functions: BTreeMap::new(),
|
|
|
|
all_functions: BTreeMap::new(),
|
|
|
|
type_iterators: BTreeMap::new(),
|
|
|
|
all_type_iterators: BTreeMap::new(),
|
2021-05-18 12:24:11 +08:00
|
|
|
indexed: true,
|
|
|
|
contains_indexed_global_functions: false,
|
|
|
|
}
|
2020-05-05 12:24:13 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get the ID of the [`Module`], if any.
|
2020-12-21 22:04:46 +08:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-12-21 22:04:46 +08:00
|
|
|
/// let mut module = Module::new();
|
2021-06-28 13:53:30 +08:00
|
|
|
/// module.set_id("hello");
|
2020-12-21 22:04:46 +08:00
|
|
|
/// assert_eq!(module.id(), Some("hello"));
|
|
|
|
/// ```
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-12-21 22:04:46 +08:00
|
|
|
pub fn id(&self) -> Option<&str> {
|
2022-01-01 17:20:00 +08:00
|
|
|
if self.id_raw().is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(self.id_raw())
|
|
|
|
}
|
2020-12-21 22:04:46 +08:00
|
|
|
}
|
|
|
|
|
2021-03-29 11:36:02 +08:00
|
|
|
/// Get the ID of the [`Module`] as an [`Identifier`], if any.
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2022-01-01 17:20:00 +08:00
|
|
|
pub(crate) const fn id_raw(&self) -> &Identifier {
|
|
|
|
&self.id
|
2020-12-21 22:04:46 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set the ID of the [`Module`].
|
2020-12-21 22:04:46 +08:00
|
|
|
///
|
2022-01-01 17:20:00 +08:00
|
|
|
/// If the string is empty, it is equivalent to clearing the ID.
|
|
|
|
///
|
2020-12-21 22:04:46 +08:00
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_id("hello");
|
|
|
|
/// assert_eq!(module.id(), Some("hello"));
|
|
|
|
/// ```
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn set_id(&mut self, id: impl Into<Identifier>) -> &mut Self {
|
2022-01-01 17:20:00 +08:00
|
|
|
self.id = id.into();
|
2021-06-28 13:53:30 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
/// Clear the ID of the [`Module`].
|
|
|
|
///
|
|
|
|
/// # Example
|
2020-12-21 22:04:46 +08:00
|
|
|
///
|
2021-06-28 13:53:30 +08:00
|
|
|
/// ```
|
|
|
|
/// # use rhai::Module;
|
2020-12-21 22:04:46 +08:00
|
|
|
/// let mut module = Module::new();
|
2021-06-28 13:53:30 +08:00
|
|
|
/// module.set_id("hello");
|
2020-12-21 22:04:46 +08:00
|
|
|
/// assert_eq!(module.id(), Some("hello"));
|
2021-06-28 13:53:30 +08:00
|
|
|
/// module.clear_id();
|
|
|
|
/// assert_eq!(module.id(), None);
|
2020-12-21 22:04:46 +08:00
|
|
|
/// ```
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-06-28 13:53:30 +08:00
|
|
|
pub fn clear_id(&mut self) -> &mut Self {
|
2022-01-01 17:20:00 +08:00
|
|
|
self.id.clear();
|
2021-04-17 18:40:16 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Is the [`Module`] empty?
|
2020-09-30 09:57:21 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-09-30 09:57:21 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-09-30 09:57:21 +08:00
|
|
|
/// let module = Module::new();
|
|
|
|
/// assert!(module.is_empty());
|
|
|
|
/// ```
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-09-30 09:57:21 +08:00
|
|
|
pub fn is_empty(&self) -> bool {
|
2021-11-27 14:24:36 +08:00
|
|
|
self.indexed
|
|
|
|
&& !self.contains_indexed_global_functions
|
|
|
|
&& self.functions.is_empty()
|
2020-09-30 09:57:21 +08:00
|
|
|
&& self.all_functions.is_empty()
|
|
|
|
&& self.variables.is_empty()
|
|
|
|
&& self.all_variables.is_empty()
|
|
|
|
&& self.modules.is_empty()
|
|
|
|
&& self.type_iterators.is_empty()
|
2020-11-16 14:07:48 +08:00
|
|
|
&& self.all_type_iterators.is_empty()
|
2020-09-30 09:57:21 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Is the [`Module`] indexed?
|
2020-11-08 14:29:54 +08:00
|
|
|
///
|
2021-04-19 15:41:24 +08:00
|
|
|
/// A module must be indexed before it can be used in an `import` statement.
|
|
|
|
///
|
2020-11-08 14:29:54 +08:00
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-11-08 14:29:54 +08:00
|
|
|
/// let mut module = Module::new();
|
2021-04-19 15:41:24 +08:00
|
|
|
/// assert!(module.is_indexed());
|
|
|
|
///
|
|
|
|
/// module.set_native_fn("foo", |x: &mut i64, y: i64| { *x = y; Ok(()) });
|
2020-11-08 14:29:54 +08:00
|
|
|
/// assert!(!module.is_indexed());
|
|
|
|
///
|
2020-11-08 16:49:59 +08:00
|
|
|
/// # #[cfg(not(feature = "no_module"))]
|
|
|
|
/// # {
|
2020-11-08 14:29:54 +08:00
|
|
|
/// module.build_index();
|
|
|
|
/// assert!(module.is_indexed());
|
2020-11-08 16:49:59 +08:00
|
|
|
/// # }
|
2020-11-08 14:29:54 +08:00
|
|
|
/// ```
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub const fn is_indexed(&self) -> bool {
|
2020-11-08 14:29:54 +08:00
|
|
|
self.indexed
|
|
|
|
}
|
|
|
|
|
2022-01-24 17:04:40 +08:00
|
|
|
/// _(metadata)_ Generate signatures for all the non-private functions in the [`Module`].
|
2021-04-02 12:34:39 +08:00
|
|
|
/// Exported under the `metadata` feature only.
|
2021-03-24 19:27:38 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-02-09 14:22:55 +08:00
|
|
|
pub fn gen_fn_signatures(&self) -> impl Iterator<Item = String> + '_ {
|
2021-12-06 11:12:54 +08:00
|
|
|
self.iter_fn()
|
2022-01-13 19:07:56 +08:00
|
|
|
.filter(|&f| match f.metadata.access {
|
2021-03-03 11:40:27 +08:00
|
|
|
FnAccess::Public => true,
|
|
|
|
FnAccess::Private => false,
|
|
|
|
})
|
2021-03-12 14:11:08 +08:00
|
|
|
.map(|f| f.gen_signature())
|
2020-11-22 17:21:34 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Does a variable exist in the [`Module`]?
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_var("answer", 42_i64);
|
|
|
|
/// assert!(module.contains_var("answer"));
|
|
|
|
/// ```
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 17:51:40 +08:00
|
|
|
pub fn contains_var(&self, name: &str) -> bool {
|
2020-05-05 15:00:10 +08:00
|
|
|
self.variables.contains_key(name)
|
2020-05-05 12:24:13 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get the value of a [`Module`] variable.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_var("answer", 42_i64);
|
2021-08-26 23:58:41 +08:00
|
|
|
/// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 17:51:40 +08:00
|
|
|
pub fn get_var_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
|
2020-05-08 00:19:08 +08:00
|
|
|
self.get_var(name).and_then(Dynamic::try_cast::<T>)
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get a [`Module`] variable as a [`Dynamic`].
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_var("answer", 42_i64);
|
2021-08-26 23:58:41 +08:00
|
|
|
/// assert_eq!(module.get_var("answer").expect("answer should exist").cast::<i64>(), 42);
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 17:51:40 +08:00
|
|
|
pub fn get_var(&self, name: &str) -> Option<Dynamic> {
|
2020-05-05 15:00:10 +08:00
|
|
|
self.variables.get(name).cloned()
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a variable into the [`Module`].
|
2020-05-05 15:00:10 +08:00
|
|
|
///
|
|
|
|
/// If there is an existing variable of the same name, it is replaced.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// module.set_var("answer", 42_i64);
|
2021-08-26 23:58:41 +08:00
|
|
|
/// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2020-12-11 12:57:07 +08:00
|
|
|
pub fn set_var(
|
|
|
|
&mut self,
|
2021-03-29 11:36:02 +08:00
|
|
|
name: impl Into<Identifier>,
|
2020-12-11 12:57:07 +08:00
|
|
|
value: impl Variant + Clone,
|
|
|
|
) -> &mut Self {
|
2021-04-17 22:19:48 +08:00
|
|
|
let ident = name.into();
|
|
|
|
let value = Dynamic::from(value);
|
|
|
|
|
|
|
|
if self.indexed {
|
2021-06-30 16:28:37 +08:00
|
|
|
let hash_var = crate::calc_qualified_var_hash(once(""), &ident);
|
2021-04-17 22:19:48 +08:00
|
|
|
self.all_variables.insert(hash_var, value.clone());
|
|
|
|
}
|
|
|
|
self.variables.insert(ident, value);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2020-11-10 23:26:50 +08:00
|
|
|
/// Get a reference to a namespace-qualified variable.
|
2021-01-02 13:29:16 +08:00
|
|
|
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
|
2021-10-29 17:01:29 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-08-14 15:10:37 +08:00
|
|
|
#[inline]
|
2021-12-25 23:49:14 +08:00
|
|
|
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> RhaiResultOf<&Dynamic> {
|
2020-12-24 16:32:43 +08:00
|
|
|
self.all_variables.get(&hash_var).ok_or_else(|| {
|
2021-12-27 12:27:31 +08:00
|
|
|
crate::ERR::ErrorVariableNotFound(String::new(), crate::Position::NONE).into()
|
2020-12-24 16:32:43 +08:00
|
|
|
})
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a script-defined function into the [`Module`].
|
2020-06-05 15:14:42 +08:00
|
|
|
///
|
|
|
|
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
2020-09-24 23:32:54 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline]
|
2021-05-08 22:59:33 +08:00
|
|
|
pub fn set_script_fn(&mut self, fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>) -> u64 {
|
2020-11-25 09:36:06 +08:00
|
|
|
let fn_def = fn_def.into();
|
|
|
|
|
2020-06-05 15:14:42 +08:00
|
|
|
// None + function name + number of arguments.
|
2020-09-24 22:50:28 +08:00
|
|
|
let num_params = fn_def.params.len();
|
2021-05-19 20:26:11 +08:00
|
|
|
let hash_script = crate::calc_fn_hash(&fn_def.name, num_params);
|
2021-12-21 13:21:29 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-13 19:07:56 +08:00
|
|
|
let params_info = fn_def.params.iter().cloned().collect();
|
2020-06-05 15:14:42 +08:00
|
|
|
self.functions.insert(
|
2020-06-11 18:13:33 +08:00
|
|
|
hash_script,
|
2021-06-29 18:25:20 +08:00
|
|
|
FuncInfo {
|
2022-01-13 19:07:56 +08:00
|
|
|
metadata: FnMetadata {
|
|
|
|
name: fn_def.name.clone(),
|
|
|
|
namespace: FnNamespace::Internal,
|
|
|
|
access: fn_def.access,
|
|
|
|
params: num_params,
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
params_info,
|
|
|
|
#[cfg(feature = "metadata")]
|
2022-01-17 23:15:22 +08:00
|
|
|
return_type: "".into(),
|
2022-01-13 19:07:56 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
comments: None,
|
|
|
|
},
|
2021-05-03 13:45:41 +08:00
|
|
|
func: Into::<CallableFunction>::into(fn_def).into(),
|
2022-01-13 19:07:56 +08:00
|
|
|
param_types: StaticVec::new_const(),
|
2021-06-29 18:25:20 +08:00
|
|
|
}
|
|
|
|
.into(),
|
2020-06-05 15:14:42 +08:00
|
|
|
);
|
2020-06-27 23:56:24 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-09-24 22:50:28 +08:00
|
|
|
hash_script
|
2020-06-05 15:14:42 +08:00
|
|
|
}
|
|
|
|
|
2021-03-12 14:11:08 +08:00
|
|
|
/// Get a shared reference to the script-defined function in the [`Module`] based on name
|
|
|
|
/// and number of parameters.
|
2020-10-05 12:09:45 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-08-14 15:10:37 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-10-05 10:27:31 +08:00
|
|
|
pub fn get_script_fn(
|
|
|
|
&self,
|
2021-11-27 23:04:45 +08:00
|
|
|
name: impl AsRef<str>,
|
2020-10-05 10:27:31 +08:00
|
|
|
num_params: usize,
|
2021-03-12 14:11:08 +08:00
|
|
|
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
2021-11-27 14:24:36 +08:00
|
|
|
if self.functions.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
2021-11-27 23:04:45 +08:00
|
|
|
let name = name.as_ref();
|
|
|
|
|
2021-12-06 11:12:54 +08:00
|
|
|
self.iter_fn()
|
2022-01-13 19:07:56 +08:00
|
|
|
.find(|f| f.metadata.params == num_params && f.metadata.name == name)
|
2021-11-27 14:24:36 +08:00
|
|
|
.and_then(|f| f.func.get_script_fn_def())
|
|
|
|
}
|
2020-10-05 10:27:31 +08:00
|
|
|
}
|
|
|
|
|
2021-03-23 12:13:53 +08:00
|
|
|
/// Get a mutable reference to the underlying [`BTreeMap`] of sub-modules.
|
2020-12-26 23:21:16 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// # WARNING
|
2020-12-26 23:21:16 +08:00
|
|
|
///
|
|
|
|
/// By taking a mutable reference, it is assumed that some sub-modules will be modified.
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Thus the [`Module`] is automatically set to be non-indexed.
|
2020-12-28 09:49:54 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-29 11:36:02 +08:00
|
|
|
pub(crate) fn sub_modules_mut(&mut self) -> &mut BTreeMap<Identifier, Shared<Module>> {
|
2020-12-26 13:05:57 +08:00
|
|
|
// We must assume that the user has changed the sub-modules
|
|
|
|
// (otherwise why take a mutable reference?)
|
2020-12-26 23:21:16 +08:00
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
|
|
|
self.all_type_iterators.clear();
|
2020-12-26 13:05:57 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-12-26 13:05:57 +08:00
|
|
|
|
|
|
|
&mut self.modules
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Does a sub-module exist in the [`Module`]?
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let sub_module = Module::new();
|
|
|
|
/// module.set_sub_module("question", sub_module);
|
|
|
|
/// assert!(module.contains_sub_module("question"));
|
|
|
|
/// ```
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 15:00:10 +08:00
|
|
|
pub fn contains_sub_module(&self, name: &str) -> bool {
|
|
|
|
self.modules.contains_key(name)
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get a sub-module in the [`Module`].
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let sub_module = Module::new();
|
|
|
|
/// module.set_sub_module("question", sub_module);
|
|
|
|
/// assert!(module.get_sub_module("question").is_some());
|
|
|
|
/// ```
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-05 15:00:10 +08:00
|
|
|
pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
|
2020-11-09 22:44:20 +08:00
|
|
|
self.modules.get(name).map(|m| m.as_ref())
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a sub-module into the [`Module`].
|
2020-05-05 15:00:10 +08:00
|
|
|
///
|
|
|
|
/// If there is an existing sub-module of the same name, it is replaced.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let sub_module = Module::new();
|
|
|
|
/// module.set_sub_module("question", sub_module);
|
|
|
|
/// assert!(module.get_sub_module("question").is_some());
|
|
|
|
/// ```
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2020-11-09 22:44:20 +08:00
|
|
|
pub fn set_sub_module(
|
|
|
|
&mut self,
|
2021-03-29 11:36:02 +08:00
|
|
|
name: impl Into<Identifier>,
|
2020-11-09 22:44:20 +08:00
|
|
|
sub_module: impl Into<Shared<Module>>,
|
|
|
|
) -> &mut Self {
|
2020-05-05 15:00:10 +08:00
|
|
|
self.modules.insert(name.into(), sub_module.into());
|
2020-06-27 23:56:24 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-05-05 15:00:10 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Does the particular Rust function exist in the [`Module`]?
|
2020-05-05 17:51:40 +08:00
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
2021-03-15 12:39:06 +08:00
|
|
|
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
|
2021-03-17 09:58:08 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2021-03-04 18:13:47 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-17 09:58:08 +08:00
|
|
|
pub fn contains_fn(&self, hash_fn: u64) -> bool {
|
|
|
|
self.functions.contains_key(&hash_fn)
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
|
|
|
|
2021-12-21 22:16:03 +08:00
|
|
|
/// _(metadata)_ Update the metadata (parameter names/types and return type) of a registered function.
|
2021-04-02 12:34:39 +08:00
|
|
|
/// Exported under the `metadata` feature only.
|
2020-11-22 17:21:34 +08:00
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
2021-01-02 23:30:10 +08:00
|
|
|
///
|
|
|
|
/// ## Parameter Names and Types
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
|
|
|
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// ## Return Type
|
|
|
|
///
|
|
|
|
/// The _last entry_ in the list should be the _return type_ of the function.
|
2020-11-22 22:15:17 +08:00
|
|
|
/// In other words, the number of entries should be one larger than the number of parameters.
|
2021-03-24 19:27:38 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2022-01-04 15:22:48 +08:00
|
|
|
pub fn update_fn_metadata<S: AsRef<str>>(
|
|
|
|
&mut self,
|
|
|
|
hash_fn: u64,
|
|
|
|
arg_names: impl AsRef<[S]>,
|
|
|
|
) -> &mut Self {
|
2021-12-21 13:21:29 +08:00
|
|
|
let mut param_names: StaticVec<_> = arg_names
|
2022-01-04 15:22:48 +08:00
|
|
|
.as_ref()
|
2021-03-24 09:56:25 +08:00
|
|
|
.iter()
|
2022-01-05 13:40:49 +08:00
|
|
|
.map(|s| s.as_ref().into())
|
2021-03-24 09:56:25 +08:00
|
|
|
.collect();
|
|
|
|
|
2021-07-26 22:22:27 +08:00
|
|
|
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
2022-01-13 19:07:56 +08:00
|
|
|
let (param_names, return_type_name) = if param_names.len() > f.metadata.params {
|
2022-01-06 11:07:52 +08:00
|
|
|
let return_type = param_names.pop().unwrap();
|
2021-12-21 13:21:29 +08:00
|
|
|
(param_names, return_type)
|
|
|
|
} else {
|
2022-01-22 17:48:07 +08:00
|
|
|
(param_names, crate::SmartString::new_const())
|
2021-12-21 13:21:29 +08:00
|
|
|
};
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.params_info = param_names;
|
|
|
|
f.metadata.return_type = return_type_name;
|
2021-07-26 22:22:27 +08:00
|
|
|
}
|
2021-05-25 10:54:48 +08:00
|
|
|
|
2020-11-22 17:21:34 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2022-01-24 17:04:40 +08:00
|
|
|
/// _(metadata)_ Update the metadata (parameter names/types, return type and doc-comments) of a registered function.
|
2021-12-21 22:16:03 +08:00
|
|
|
/// Exported under the `metadata` feature only.
|
|
|
|
///
|
|
|
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
|
|
|
///
|
|
|
|
/// ## Parameter Names and Types
|
|
|
|
///
|
|
|
|
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
|
|
|
///
|
|
|
|
/// ## Return Type
|
|
|
|
///
|
|
|
|
/// The _last entry_ in the list should be the _return type_ of the function. In other words,
|
|
|
|
/// the number of entries should be one larger than the number of parameters.
|
|
|
|
///
|
|
|
|
/// ## Comments
|
|
|
|
///
|
|
|
|
/// Block doc-comments should be kept in a single line.
|
|
|
|
///
|
|
|
|
/// Line doc-comments should be kept in one string slice per line without the termination line-break.
|
|
|
|
///
|
|
|
|
/// Leading white-spaces should be stripped, and each string slice always starts with the corresponding
|
|
|
|
/// doc-comment leader: `///` or `/**`.
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
#[inline]
|
2022-01-04 15:22:48 +08:00
|
|
|
pub fn update_fn_metadata_with_comments<A: AsRef<str>, C: AsRef<str>>(
|
2021-12-21 22:16:03 +08:00
|
|
|
&mut self,
|
|
|
|
hash_fn: u64,
|
2022-01-04 15:22:48 +08:00
|
|
|
arg_names: impl AsRef<[A]>,
|
|
|
|
comments: impl AsRef<[C]>,
|
2021-12-21 22:16:03 +08:00
|
|
|
) -> &mut Self {
|
|
|
|
self.update_fn_metadata(hash_fn, arg_names);
|
|
|
|
|
2022-01-04 22:16:20 +08:00
|
|
|
let comments = comments.as_ref();
|
|
|
|
|
|
|
|
if !comments.is_empty() {
|
2022-01-06 11:07:52 +08:00
|
|
|
let f = self.functions.get_mut(&hash_fn).unwrap();
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.comments = Some(comments.iter().map(|s| s.as_ref().into()).collect());
|
2021-12-21 22:16:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-12-07 21:54:52 +08:00
|
|
|
/// Update the namespace of a registered function.
|
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2021-03-08 15:30:32 +08:00
|
|
|
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
|
2020-12-07 21:54:52 +08:00
|
|
|
if let Some(f) = self.functions.get_mut(&hash_fn) {
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.namespace = namespace;
|
2021-03-24 09:56:25 +08:00
|
|
|
self.indexed = false;
|
|
|
|
self.contains_indexed_global_functions = false;
|
2020-12-07 21:54:52 +08:00
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-03-26 10:59:34 +08:00
|
|
|
/// Remap type ID.
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-26 10:59:34 +08:00
|
|
|
fn map_type(map: bool, type_id: TypeId) -> TypeId {
|
|
|
|
if !map {
|
|
|
|
return type_id;
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<&str>() {
|
|
|
|
// Map &str to ImmutableString
|
|
|
|
return TypeId::of::<ImmutableString>();
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<String>() {
|
|
|
|
// Map String to ImmutableString
|
|
|
|
return TypeId::of::<ImmutableString>();
|
|
|
|
}
|
|
|
|
|
|
|
|
type_id
|
|
|
|
}
|
|
|
|
|
2021-12-06 10:34:13 +08:00
|
|
|
/// Set a Rust function into the [`Module`], returning a non-zero hash key.
|
2020-05-05 17:51:40 +08:00
|
|
|
///
|
|
|
|
/// If there is an existing Rust function of the same hash, it is replaced.
|
2020-07-11 15:09:17 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// # WARNING - Low Level API
|
2020-07-11 15:09:17 +08:00
|
|
|
///
|
|
|
|
/// This function is very low level.
|
2021-12-21 13:21:29 +08:00
|
|
|
///
|
|
|
|
/// ## Parameter Names and Types
|
|
|
|
///
|
|
|
|
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
|
|
|
///
|
|
|
|
/// ## Return Type
|
|
|
|
///
|
|
|
|
/// The _last entry_ in the list should be the _return type_ of the function.
|
|
|
|
/// In other words, the number of entries should be one larger than the number of parameters.
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline]
|
2020-07-11 15:09:17 +08:00
|
|
|
pub fn set_fn(
|
2020-05-22 21:50:24 +08:00
|
|
|
&mut self,
|
2022-01-04 15:22:48 +08:00
|
|
|
name: impl AsRef<str>,
|
2020-11-17 12:23:53 +08:00
|
|
|
namespace: FnNamespace,
|
2020-05-22 21:50:24 +08:00
|
|
|
access: FnAccess,
|
2021-11-27 23:04:45 +08:00
|
|
|
arg_names: Option<&[&str]>,
|
2022-01-04 15:22:48 +08:00
|
|
|
arg_types: impl AsRef<[TypeId]>,
|
2020-09-25 18:07:39 +08:00
|
|
|
func: CallableFunction,
|
2021-03-08 15:30:32 +08:00
|
|
|
) -> u64 {
|
2021-11-27 23:04:45 +08:00
|
|
|
let _arg_names = arg_names;
|
2021-03-08 15:30:32 +08:00
|
|
|
let is_method = func.is_method();
|
2020-09-11 22:32:59 +08:00
|
|
|
|
2021-05-05 18:38:52 +08:00
|
|
|
let mut param_types: StaticVec<_> = arg_types
|
2022-01-04 15:22:48 +08:00
|
|
|
.as_ref()
|
2021-03-08 15:30:32 +08:00
|
|
|
.iter()
|
2020-09-19 18:12:23 +08:00
|
|
|
.cloned()
|
2021-03-08 15:30:32 +08:00
|
|
|
.enumerate()
|
2021-03-26 10:59:34 +08:00
|
|
|
.map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id))
|
|
|
|
.collect();
|
2021-05-05 18:38:52 +08:00
|
|
|
param_types.shrink_to_fit();
|
2021-03-26 10:59:34 +08:00
|
|
|
|
|
|
|
#[cfg(feature = "metadata")]
|
2021-12-21 13:21:29 +08:00
|
|
|
let (param_names, return_type_name) = {
|
|
|
|
let mut names = _arg_names
|
|
|
|
.iter()
|
|
|
|
.flat_map(|&p| p.iter())
|
2022-01-05 13:40:49 +08:00
|
|
|
.map(|&s| s.into())
|
2021-12-21 13:21:29 +08:00
|
|
|
.collect::<StaticVec<_>>();
|
2022-01-04 15:22:48 +08:00
|
|
|
let return_type = if names.len() > arg_types.as_ref().len() {
|
2022-01-06 11:07:52 +08:00
|
|
|
names.pop().unwrap()
|
2021-12-21 13:21:29 +08:00
|
|
|
} else {
|
2022-01-22 17:48:07 +08:00
|
|
|
crate::SmartString::new_const()
|
2021-12-21 13:21:29 +08:00
|
|
|
};
|
|
|
|
names.shrink_to_fit();
|
|
|
|
(names, return_type)
|
|
|
|
};
|
2020-05-17 22:19:49 +08:00
|
|
|
|
2021-11-28 12:41:20 +08:00
|
|
|
let hash_fn = calc_native_fn_hash(empty::<&str>(), name.as_ref(), ¶m_types);
|
2021-03-08 15:30:32 +08:00
|
|
|
|
2021-03-26 10:59:34 +08:00
|
|
|
self.functions.insert(
|
|
|
|
hash_fn,
|
2021-06-29 18:25:20 +08:00
|
|
|
FuncInfo {
|
2022-01-13 19:07:56 +08:00
|
|
|
metadata: FnMetadata {
|
|
|
|
name: name.as_ref().into(),
|
|
|
|
namespace,
|
|
|
|
access,
|
|
|
|
params: param_types.len(),
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
params_info: param_names,
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
return_type: return_type_name,
|
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
comments: None,
|
|
|
|
},
|
2021-05-03 13:45:41 +08:00
|
|
|
func: func.into(),
|
2022-01-13 19:07:56 +08:00
|
|
|
param_types,
|
2021-06-29 18:25:20 +08:00
|
|
|
}
|
|
|
|
.into(),
|
2021-03-26 10:59:34 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
self.indexed = false;
|
|
|
|
self.contains_indexed_global_functions = false;
|
|
|
|
|
|
|
|
hash_fn
|
|
|
|
}
|
|
|
|
|
2021-12-21 16:14:07 +08:00
|
|
|
/// _(metadata)_ Set a Rust function into the [`Module`], returning a non-zero hash key.
|
|
|
|
/// Exported under the `metadata` feature only.
|
|
|
|
///
|
|
|
|
/// If there is an existing Rust function of the same hash, it is replaced.
|
|
|
|
///
|
|
|
|
/// # WARNING - Low Level API
|
|
|
|
///
|
|
|
|
/// This function is very low level.
|
|
|
|
///
|
|
|
|
/// ## Parameter Names and Types
|
|
|
|
///
|
|
|
|
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
|
|
|
///
|
|
|
|
/// ## Return Type
|
|
|
|
///
|
|
|
|
/// The _last entry_ in the list should be the _return type_ of the function.
|
|
|
|
/// In other words, the number of entries should be one larger than the number of parameters.
|
2021-12-21 22:16:03 +08:00
|
|
|
///
|
|
|
|
/// ## Comments
|
|
|
|
///
|
|
|
|
/// Block doc-comments should be kept in a single line.
|
|
|
|
///
|
|
|
|
/// Line doc-comments should be kept in one string slice per line without the termination line-break.
|
|
|
|
///
|
|
|
|
/// Leading white-spaces should be stripped, and each string slice always starts with the corresponding
|
|
|
|
/// doc-comment leader: `///` or `/**`.
|
2021-12-21 16:14:07 +08:00
|
|
|
#[cfg(feature = "metadata")]
|
|
|
|
#[inline]
|
2022-01-04 15:22:48 +08:00
|
|
|
pub fn set_fn_with_comments<S: AsRef<str>>(
|
2021-12-21 16:14:07 +08:00
|
|
|
&mut self,
|
2022-01-04 15:22:48 +08:00
|
|
|
name: impl AsRef<str>,
|
2021-12-21 16:14:07 +08:00
|
|
|
namespace: FnNamespace,
|
|
|
|
access: FnAccess,
|
|
|
|
arg_names: Option<&[&str]>,
|
2022-01-04 15:22:48 +08:00
|
|
|
arg_types: impl AsRef<[TypeId]>,
|
|
|
|
comments: impl AsRef<[S]>,
|
2021-12-21 16:14:07 +08:00
|
|
|
func: CallableFunction,
|
|
|
|
) -> u64 {
|
|
|
|
let hash = self.set_fn(name, namespace, access, arg_names, arg_types, func);
|
|
|
|
|
2022-01-04 22:16:20 +08:00
|
|
|
let comments = comments.as_ref();
|
|
|
|
|
|
|
|
if !comments.is_empty() {
|
2022-01-06 11:07:52 +08:00
|
|
|
let f = self.functions.get_mut(&hash).unwrap();
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.comments = Some(comments.iter().map(|s| s.as_ref().into()).collect());
|
2021-12-21 16:14:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
hash
|
|
|
|
}
|
|
|
|
|
2020-11-20 16:52:28 +08:00
|
|
|
/// Set a Rust function taking a reference to the scripting [`Engine`][crate::Engine],
|
2020-12-26 23:21:16 +08:00
|
|
|
/// the current set of functions, plus a list of mutable [`Dynamic`] references
|
2021-12-06 10:34:13 +08:00
|
|
|
/// into the [`Module`], returning a non-zero hash key.
|
2020-06-15 21:49:02 +08:00
|
|
|
///
|
|
|
|
/// Use this to register a built-in function which must reference settings on the scripting
|
2020-11-20 16:52:28 +08:00
|
|
|
/// [`Engine`][crate::Engine] (e.g. to prevent growing an array beyond the allowed maximum size),
|
|
|
|
/// or to call a script-defined function in the current evaluation context.
|
2020-06-15 21:49:02 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing Rust function, it is replaced.
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// # WARNING - Low Level API
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
|
|
|
/// This function is very low level.
|
|
|
|
///
|
2021-12-27 11:43:11 +08:00
|
|
|
/// # Arguments
|
2021-03-03 11:40:27 +08:00
|
|
|
///
|
2020-11-20 16:52:28 +08:00
|
|
|
/// A list of [`TypeId`]'s is taken as the argument types.
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Arguments are simply passed in as a mutable array of [`&mut Dynamic`][Dynamic],
|
2020-07-07 22:59:23 +08:00
|
|
|
/// which is guaranteed to contain enough arguments of the correct types.
|
|
|
|
///
|
2020-10-03 16:25:58 +08:00
|
|
|
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
|
|
|
|
/// All other arguments can be consumed.
|
|
|
|
///
|
2021-03-03 18:13:41 +08:00
|
|
|
/// To access a primary argument value (i.e. cloning is cheap), use: `args[n].as_xxx().unwrap()`
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
2021-03-03 11:40:27 +08:00
|
|
|
/// To access an argument value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
|
2020-07-07 22:59:23 +08:00
|
|
|
/// Notice that this will _consume_ the argument, replacing it with `()`.
|
|
|
|
///
|
2021-03-03 11:40:27 +08:00
|
|
|
/// To access the first mutable argument, use `args.get_mut(0).unwrap()`
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered. Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2020-11-17 12:23:53 +08:00
|
|
|
/// use rhai::{Module, FnNamespace, FnAccess};
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
|
|
|
/// let mut module = Module::new();
|
2020-11-17 15:11:58 +08:00
|
|
|
/// let hash = module.set_raw_fn("double_or_not", FnNamespace::Internal, FnAccess::Public,
|
2020-07-07 22:59:23 +08:00
|
|
|
/// // Pass parameter types via a slice with TypeId's
|
2020-07-28 10:25:57 +08:00
|
|
|
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>()],
|
2020-07-07 22:59:23 +08:00
|
|
|
/// // Fixed closure signature
|
2020-10-18 17:08:57 +08:00
|
|
|
/// |context, args| {
|
2020-07-07 22:59:23 +08:00
|
|
|
/// // 'args' is guaranteed to be the right length and of the correct types
|
|
|
|
///
|
|
|
|
/// // Get the second parameter by 'consuming' it
|
|
|
|
/// let double = std::mem::take(args[1]).cast::<bool>();
|
|
|
|
/// // Since it is a primary type, it can also be cheaply copied
|
2021-03-30 18:57:16 +08:00
|
|
|
/// let double = args[1].clone_cast::<bool>();
|
2020-07-07 22:59:23 +08:00
|
|
|
/// // Get a mutable reference to the first argument.
|
2020-07-27 11:30:09 +07:00
|
|
|
/// let mut x = args[0].write_lock::<i64>().unwrap();
|
2020-07-07 22:59:23 +08:00
|
|
|
///
|
|
|
|
/// let orig = *x;
|
|
|
|
///
|
|
|
|
/// if double {
|
|
|
|
/// *x *= 2; // the first argument can be mutated
|
|
|
|
/// }
|
|
|
|
///
|
2021-12-25 23:49:14 +08:00
|
|
|
/// Ok(orig) // return RhaiResult<T>
|
2020-07-07 22:59:23 +08:00
|
|
|
/// });
|
|
|
|
///
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-07-07 22:59:23 +08:00
|
|
|
/// ```
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2022-01-04 15:22:48 +08:00
|
|
|
pub fn set_raw_fn<T, F>(
|
2020-06-15 21:49:02 +08:00
|
|
|
&mut self,
|
2022-01-04 15:22:48 +08:00
|
|
|
name: impl AsRef<str>,
|
2020-11-17 12:23:53 +08:00
|
|
|
namespace: FnNamespace,
|
|
|
|
access: FnAccess,
|
2022-01-04 15:22:48 +08:00
|
|
|
arg_types: impl AsRef<[TypeId]>,
|
2021-03-24 13:17:52 +08:00
|
|
|
func: F,
|
|
|
|
) -> u64
|
|
|
|
where
|
|
|
|
T: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
|
2021-03-24 13:17:52 +08:00
|
|
|
{
|
2020-11-02 11:04:45 +08:00
|
|
|
let f =
|
|
|
|
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
|
2020-11-17 12:23:53 +08:00
|
|
|
|
2020-09-25 18:07:39 +08:00
|
|
|
self.set_fn(
|
|
|
|
name,
|
2020-11-17 12:23:53 +08:00
|
|
|
namespace,
|
|
|
|
access,
|
2020-11-22 17:21:34 +08:00
|
|
|
None,
|
2020-09-25 18:07:39 +08:00
|
|
|
arg_types,
|
|
|
|
CallableFunction::from_method(Box::new(f)),
|
|
|
|
)
|
2020-06-15 21:49:02 +08:00
|
|
|
}
|
|
|
|
|
2021-12-06 10:34:13 +08:00
|
|
|
/// Set a Rust function into the [`Module`], returning a non-zero hash key.
|
2020-05-05 17:51:40 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing Rust function, it is replaced.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// # Function Namespace
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// The default function namespace is [`FnNamespace::Internal`].
|
|
|
|
/// Use [`update_fn_namespace`][Module::update_fn_namespace] to change it.
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// let mut module = Module::new();
|
2021-03-15 12:39:06 +08:00
|
|
|
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-05-06 19:45:17 +08:00
|
|
|
/// ```
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-03-24 13:17:52 +08:00
|
|
|
pub fn set_native_fn<ARGS, N, T, F>(&mut self, name: N, func: F) -> u64
|
2021-03-15 12:39:06 +08:00
|
|
|
where
|
2021-03-29 11:36:02 +08:00
|
|
|
N: AsRef<str> + Into<Identifier>,
|
2021-03-15 12:39:06 +08:00
|
|
|
T: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>,
|
2021-03-15 12:39:06 +08:00
|
|
|
{
|
2020-09-25 18:07:39 +08:00
|
|
|
self.set_fn(
|
|
|
|
name,
|
2020-11-17 12:23:53 +08:00
|
|
|
FnNamespace::Internal,
|
2020-10-01 23:31:27 +08:00
|
|
|
FnAccess::Public,
|
2020-11-22 17:21:34 +08:00
|
|
|
None,
|
2021-03-15 12:39:06 +08:00
|
|
|
&F::param_types(),
|
|
|
|
func.into_callable_function(),
|
2020-09-25 18:07:39 +08:00
|
|
|
)
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
|
|
|
|
2021-12-06 10:34:13 +08:00
|
|
|
/// Set a Rust getter function taking one mutable parameter, returning a non-zero hash key.
|
2020-11-17 15:11:58 +08:00
|
|
|
/// This function is automatically exposed to the global namespace.
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing Rust getter function, it is replaced.
|
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
2021-06-28 13:53:30 +08:00
|
|
|
/// # use rhai::Module;
|
2020-05-30 10:28:17 +08:00
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let hash = module.set_getter_fn("value", |x: &mut i64| { Ok(*x) });
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-05-30 10:28:17 +08:00
|
|
|
/// ```
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-11-27 23:04:45 +08:00
|
|
|
pub fn set_getter_fn<ARGS, A, T, F>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
2021-03-15 12:39:06 +08:00
|
|
|
where
|
|
|
|
A: Variant + Clone,
|
|
|
|
T: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>,
|
|
|
|
F: Fn(&mut A) -> RhaiResultOf<T> + SendSync + 'static,
|
2021-03-15 12:39:06 +08:00
|
|
|
{
|
|
|
|
self.set_fn(
|
2022-01-04 15:22:48 +08:00
|
|
|
crate::engine::make_getter(name.as_ref()).as_str(),
|
2020-11-17 15:11:58 +08:00
|
|
|
FnNamespace::Global,
|
2020-10-01 23:31:27 +08:00
|
|
|
FnAccess::Public,
|
2020-11-22 17:21:34 +08:00
|
|
|
None,
|
2021-03-15 12:39:06 +08:00
|
|
|
&F::param_types(),
|
|
|
|
func.into_callable_function(),
|
2020-09-25 18:07:39 +08:00
|
|
|
)
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a Rust setter function taking two parameters (the first one mutable) into the [`Module`],
|
2021-12-06 10:34:13 +08:00
|
|
|
/// returning a non-zero hash key.
|
2020-11-17 15:11:58 +08:00
|
|
|
/// This function is automatically exposed to the global namespace.
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing setter Rust function, it is replaced.
|
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::{Module, ImmutableString};
|
|
|
|
///
|
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let hash = module.set_setter_fn("value", |x: &mut i64, y: ImmutableString| {
|
|
|
|
/// *x = y.len() as i64;
|
|
|
|
/// Ok(())
|
|
|
|
/// });
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-05-30 10:28:17 +08:00
|
|
|
/// ```
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-11-27 23:04:45 +08:00
|
|
|
pub fn set_setter_fn<ARGS, A, B, F>(&mut self, name: impl AsRef<str>, func: F) -> u64
|
2021-03-15 12:39:06 +08:00
|
|
|
where
|
|
|
|
A: Variant + Clone,
|
|
|
|
B: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>,
|
|
|
|
F: Fn(&mut A, B) -> RhaiResultOf<()> + SendSync + 'static,
|
2021-03-15 12:39:06 +08:00
|
|
|
{
|
|
|
|
self.set_fn(
|
2022-01-04 15:22:48 +08:00
|
|
|
crate::engine::make_setter(name.as_ref()).as_str(),
|
2020-11-17 15:11:58 +08:00
|
|
|
FnNamespace::Global,
|
2021-03-15 12:39:06 +08:00
|
|
|
FnAccess::Public,
|
|
|
|
None,
|
|
|
|
&F::param_types(),
|
|
|
|
func.into_callable_function(),
|
2020-11-17 15:11:58 +08:00
|
|
|
)
|
2020-05-30 10:28:17 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a Rust index getter taking two parameters (the first one mutable) into the [`Module`],
|
2021-12-06 10:34:13 +08:00
|
|
|
/// returning a non-zero hash key.
|
2020-11-17 15:11:58 +08:00
|
|
|
/// This function is automatically exposed to the global namespace.
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing setter Rust function, it is replaced.
|
|
|
|
///
|
2020-09-22 17:57:56 +08:00
|
|
|
/// # Panics
|
|
|
|
///
|
2021-12-06 20:52:47 +08:00
|
|
|
/// Panics if the type is [`Array`][crate::Array] or [`Map`][crate::Map].
|
2020-09-22 17:57:56 +08:00
|
|
|
/// Indexers for arrays, object maps and strings cannot be registered.
|
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-30 10:28:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::{Module, ImmutableString};
|
|
|
|
///
|
|
|
|
/// let mut module = Module::new();
|
2020-06-06 13:06:00 +08:00
|
|
|
/// let hash = module.set_indexer_get_fn(|x: &mut i64, y: ImmutableString| {
|
2020-05-30 10:28:17 +08:00
|
|
|
/// Ok(*x + y.len() as i64)
|
|
|
|
/// });
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-05-30 10:28:17 +08:00
|
|
|
/// ```
|
2021-05-18 20:12:30 +08:00
|
|
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
2021-08-14 15:10:37 +08:00
|
|
|
#[inline]
|
2021-03-15 12:39:06 +08:00
|
|
|
pub fn set_indexer_get_fn<ARGS, A, B, T, F>(&mut self, func: F) -> u64
|
|
|
|
where
|
|
|
|
A: Variant + Clone,
|
|
|
|
B: Variant + Clone,
|
|
|
|
T: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>,
|
|
|
|
F: Fn(&mut A, B) -> RhaiResultOf<T> + SendSync + 'static,
|
2021-03-15 12:39:06 +08:00
|
|
|
{
|
2021-05-18 20:12:30 +08:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-12-06 20:52:47 +08:00
|
|
|
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
2020-09-22 17:57:56 +08:00
|
|
|
panic!("Cannot register indexer for arrays.");
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-12-06 20:52:47 +08:00
|
|
|
if TypeId::of::<A>() == TypeId::of::<crate::Map>() {
|
2020-09-22 17:57:56 +08:00
|
|
|
panic!("Cannot register indexer for object maps.");
|
|
|
|
}
|
|
|
|
if TypeId::of::<A>() == TypeId::of::<String>()
|
|
|
|
|| TypeId::of::<A>() == TypeId::of::<&str>()
|
|
|
|
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
|
|
|
|
{
|
|
|
|
panic!("Cannot register indexer for strings.");
|
|
|
|
}
|
|
|
|
|
2020-09-25 18:07:39 +08:00
|
|
|
self.set_fn(
|
2021-03-15 12:39:06 +08:00
|
|
|
crate::engine::FN_IDX_GET,
|
|
|
|
FnNamespace::Global,
|
2020-10-01 23:31:27 +08:00
|
|
|
FnAccess::Public,
|
2020-11-22 17:21:34 +08:00
|
|
|
None,
|
2021-03-15 12:39:06 +08:00
|
|
|
&F::param_types(),
|
|
|
|
func.into_callable_function(),
|
2020-09-25 18:07:39 +08:00
|
|
|
)
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a Rust index setter taking three parameters (the first one mutable) into the [`Module`],
|
2021-12-06 10:34:13 +08:00
|
|
|
/// returning a non-zero hash key.
|
2020-11-17 15:11:58 +08:00
|
|
|
/// This function is automatically exposed to the global namespace.
|
2020-06-06 13:06:00 +08:00
|
|
|
///
|
|
|
|
/// If there is a similar existing Rust function, it is replaced.
|
|
|
|
///
|
2020-09-22 17:57:56 +08:00
|
|
|
/// # Panics
|
|
|
|
///
|
2021-12-06 20:52:47 +08:00
|
|
|
/// Panics if the type is [`Array`][crate::Array] or [`Map`][crate::Map].
|
2020-09-22 17:57:56 +08:00
|
|
|
/// Indexers for arrays, object maps and strings cannot be registered.
|
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-06-06 13:06:00 +08:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::{Module, ImmutableString};
|
|
|
|
///
|
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let hash = module.set_indexer_set_fn(|x: &mut i64, y: ImmutableString, value: i64| {
|
2021-04-19 15:41:24 +08:00
|
|
|
/// *x = y.len() as i64 + value; Ok(())
|
2020-06-06 13:06:00 +08:00
|
|
|
/// });
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash));
|
2020-06-06 13:06:00 +08:00
|
|
|
/// ```
|
2021-05-18 20:12:30 +08:00
|
|
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
2021-08-14 15:10:37 +08:00
|
|
|
#[inline]
|
2021-03-15 12:39:06 +08:00
|
|
|
pub fn set_indexer_set_fn<ARGS, A, B, C, F>(&mut self, func: F) -> u64
|
|
|
|
where
|
|
|
|
A: Variant + Clone,
|
|
|
|
B: Variant + Clone,
|
|
|
|
C: Variant + Clone,
|
2021-12-25 23:49:14 +08:00
|
|
|
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>,
|
|
|
|
F: Fn(&mut A, B, C) -> RhaiResultOf<()> + SendSync + 'static,
|
2021-03-15 12:39:06 +08:00
|
|
|
{
|
2021-05-18 20:12:30 +08:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-12-06 20:52:47 +08:00
|
|
|
if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
|
2020-09-22 17:57:56 +08:00
|
|
|
panic!("Cannot register indexer for arrays.");
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-12-06 20:52:47 +08:00
|
|
|
if TypeId::of::<A>() == TypeId::of::<crate::Map>() {
|
2020-09-22 17:57:56 +08:00
|
|
|
panic!("Cannot register indexer for object maps.");
|
|
|
|
}
|
|
|
|
if TypeId::of::<A>() == TypeId::of::<String>()
|
|
|
|
|| TypeId::of::<A>() == TypeId::of::<&str>()
|
|
|
|
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
|
|
|
|
{
|
|
|
|
panic!("Cannot register indexer for strings.");
|
|
|
|
}
|
|
|
|
|
2020-06-06 13:06:00 +08:00
|
|
|
self.set_fn(
|
2020-11-16 16:28:04 +08:00
|
|
|
crate::engine::FN_IDX_SET,
|
2021-03-15 12:39:06 +08:00
|
|
|
FnNamespace::Global,
|
2020-10-01 23:31:27 +08:00
|
|
|
FnAccess::Public,
|
2020-11-22 17:21:34 +08:00
|
|
|
None,
|
2021-03-15 12:39:06 +08:00
|
|
|
&F::param_types(),
|
|
|
|
func.into_callable_function(),
|
2020-06-06 13:06:00 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-12-06 10:34:13 +08:00
|
|
|
/// Set a pair of Rust index getter and setter functions, returning both non-zero hash keys.
|
2020-11-20 16:52:28 +08:00
|
|
|
/// This is a short-hand for [`set_indexer_get_fn`][Module::set_indexer_get_fn] and
|
|
|
|
/// [`set_indexer_set_fn`][Module::set_indexer_set_fn].
|
2020-07-24 23:16:54 +08:00
|
|
|
///
|
|
|
|
/// If there are similar existing Rust functions, they are replaced.
|
|
|
|
///
|
2020-09-22 17:57:56 +08:00
|
|
|
/// # Panics
|
|
|
|
///
|
2021-12-06 20:52:47 +08:00
|
|
|
/// Panics if the type is [`Array`][crate::Array] or [`Map`][crate::Map].
|
2020-09-22 17:57:56 +08:00
|
|
|
/// Indexers for arrays, object maps and strings cannot be registered.
|
|
|
|
///
|
2020-11-22 22:15:17 +08:00
|
|
|
/// # Function Metadata
|
|
|
|
///
|
2021-12-21 22:16:03 +08:00
|
|
|
/// No metadata for the function is registered.
|
|
|
|
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
|
2020-11-22 22:15:17 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-07-24 23:16:54 +08:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::{Module, ImmutableString};
|
|
|
|
///
|
|
|
|
/// let mut module = Module::new();
|
|
|
|
/// let (hash_get, hash_set) = module.set_indexer_get_set_fn(
|
|
|
|
/// |x: &mut i64, y: ImmutableString| {
|
|
|
|
/// Ok(*x + y.len() as i64)
|
|
|
|
/// },
|
|
|
|
/// |x: &mut i64, y: ImmutableString, value: i64| {
|
2021-04-19 15:41:24 +08:00
|
|
|
/// *x = y.len() as i64 + value; Ok(())
|
2020-07-24 23:16:54 +08:00
|
|
|
/// }
|
|
|
|
/// );
|
2021-03-17 14:45:40 +08:00
|
|
|
/// assert!(module.contains_fn(hash_get));
|
|
|
|
/// assert!(module.contains_fn(hash_set));
|
2020-07-24 23:16:54 +08:00
|
|
|
/// ```
|
2021-05-18 20:12:30 +08:00
|
|
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
2021-01-03 13:29:42 +08:00
|
|
|
#[inline(always)]
|
2021-03-24 13:17:52 +08:00
|
|
|
pub fn set_indexer_get_set_fn<A, B, T>(
|
2020-07-24 23:16:54 +08:00
|
|
|
&mut self,
|
2021-12-25 23:49:14 +08:00
|
|
|
get_fn: impl Fn(&mut A, B) -> RhaiResultOf<T> + SendSync + 'static,
|
|
|
|
set_fn: impl Fn(&mut A, B, T) -> RhaiResultOf<()> + SendSync + 'static,
|
2021-03-24 13:17:52 +08:00
|
|
|
) -> (u64, u64)
|
|
|
|
where
|
|
|
|
A: Variant + Clone,
|
|
|
|
B: Variant + Clone,
|
|
|
|
T: Variant + Clone,
|
|
|
|
{
|
2020-07-24 23:16:54 +08:00
|
|
|
(
|
2021-02-13 10:56:09 +08:00
|
|
|
self.set_indexer_get_fn(get_fn),
|
|
|
|
self.set_indexer_set_fn(set_fn),
|
2020-07-24 23:16:54 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-05-05 17:51:40 +08:00
|
|
|
/// Get a Rust function.
|
|
|
|
///
|
2021-03-15 12:39:06 +08:00
|
|
|
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-17 09:58:08 +08:00
|
|
|
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
|
2021-05-03 13:45:41 +08:00
|
|
|
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Does the particular namespace-qualified function exist in the [`Module`]?
|
2020-11-16 14:07:48 +08:00
|
|
|
///
|
2021-03-08 15:30:32 +08:00
|
|
|
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
|
2020-12-24 16:32:43 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-08 15:30:32 +08:00
|
|
|
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
|
2020-12-24 16:32:43 +08:00
|
|
|
self.all_functions.contains_key(&hash_fn)
|
2020-11-16 14:07:48 +08:00
|
|
|
}
|
|
|
|
|
2020-11-10 23:26:50 +08:00
|
|
|
/// Get a namespace-qualified function.
|
2020-05-05 17:51:40 +08:00
|
|
|
///
|
2021-03-08 15:30:32 +08:00
|
|
|
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-08 15:30:32 +08:00
|
|
|
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
|
2021-05-03 13:45:41 +08:00
|
|
|
self.all_functions
|
|
|
|
.get(&hash_qualified_fn)
|
|
|
|
.map(|f| f.as_ref())
|
2020-05-05 17:51:40 +08:00
|
|
|
}
|
2020-05-05 23:57:25 +08:00
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Combine another [`Module`] into this [`Module`].
|
|
|
|
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline]
|
2020-08-15 00:04:10 +08:00
|
|
|
pub fn combine(&mut self, other: Self) -> &mut Self {
|
2020-10-25 00:39:47 +08:00
|
|
|
self.modules.extend(other.modules.into_iter());
|
|
|
|
self.variables.extend(other.variables.into_iter());
|
|
|
|
self.functions.extend(other.functions.into_iter());
|
|
|
|
self.type_iterators.extend(other.type_iterators.into_iter());
|
2020-08-21 21:48:45 +08:00
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
2020-11-16 14:07:48 +08:00
|
|
|
self.all_type_iterators.clear();
|
2020-08-21 21:48:45 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-08-21 21:48:45 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Combine another [`Module`] into this [`Module`].
|
|
|
|
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
|
|
|
|
/// Sub-modules are flattened onto the root [`Module`], with higher level overriding lower level.
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline]
|
2020-08-21 21:48:45 +08:00
|
|
|
pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
|
2022-01-28 18:59:18 +08:00
|
|
|
for (_, m) in other.modules.into_iter() {
|
2020-11-09 22:44:20 +08:00
|
|
|
self.combine_flatten(shared_take_or_clone(m));
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-10-25 00:39:47 +08:00
|
|
|
self.variables.extend(other.variables.into_iter());
|
|
|
|
self.functions.extend(other.functions.into_iter());
|
|
|
|
self.type_iterators.extend(other.type_iterators.into_iter());
|
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
2020-11-16 14:07:48 +08:00
|
|
|
self.all_type_iterators.clear();
|
2020-10-25 00:39:47 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-10-25 00:39:47 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Polyfill this [`Module`] with another [`Module`].
|
|
|
|
/// Only items not existing in this [`Module`] are added.
|
2020-10-25 00:39:47 +08:00
|
|
|
#[inline]
|
|
|
|
pub fn fill_with(&mut self, other: &Self) -> &mut Self {
|
2022-01-28 18:59:18 +08:00
|
|
|
for (k, v) in &other.modules {
|
2020-10-25 00:39:47 +08:00
|
|
|
if !self.modules.contains_key(k) {
|
|
|
|
self.modules.insert(k.clone(), v.clone());
|
|
|
|
}
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
|
|
|
for (k, v) in &other.variables {
|
2020-10-25 00:39:47 +08:00
|
|
|
if !self.variables.contains_key(k) {
|
|
|
|
self.variables.insert(k.clone(), v.clone());
|
|
|
|
}
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
|
|
|
for (&k, v) in &other.functions {
|
2020-10-25 00:39:47 +08:00
|
|
|
self.functions.entry(k).or_insert_with(|| v.clone());
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
|
|
|
for (&k, v) in &other.type_iterators {
|
2022-01-27 23:55:32 +08:00
|
|
|
self.type_iterators.entry(k).or_insert(v.clone());
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-08-15 00:04:10 +08:00
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
2020-11-16 14:07:48 +08:00
|
|
|
self.all_type_iterators.clear();
|
2020-08-15 00:04:10 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-08-15 00:04:10 +08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Merge another [`Module`] into this [`Module`].
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2020-07-12 11:46:53 +08:00
|
|
|
pub fn merge(&mut self, other: &Self) -> &mut Self {
|
2022-01-20 08:17:34 +08:00
|
|
|
self.merge_filtered(other, |_, _, _, _, _| true)
|
2020-06-30 18:34:58 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Merge another [`Module`] into this [`Module`] based on a filter predicate.
|
2020-06-30 18:34:58 +08:00
|
|
|
pub(crate) fn merge_filtered(
|
|
|
|
&mut self,
|
|
|
|
other: &Self,
|
2022-01-20 08:17:34 +08:00
|
|
|
_filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool + Copy,
|
2020-07-12 11:46:53 +08:00
|
|
|
) -> &mut Self {
|
2022-01-28 18:59:18 +08:00
|
|
|
for (k, v) in &other.modules {
|
2020-10-25 00:39:47 +08:00
|
|
|
let mut m = Self::new();
|
|
|
|
m.merge_filtered(v, _filter);
|
2020-12-11 12:57:07 +08:00
|
|
|
self.set_sub_module(k.clone(), m);
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-08-21 21:48:45 +08:00
|
|
|
#[cfg(feature = "no_function")]
|
2020-10-25 00:39:47 +08:00
|
|
|
self.modules
|
|
|
|
.extend(other.modules.iter().map(|(k, v)| (k.clone(), v.clone())));
|
|
|
|
|
|
|
|
self.variables
|
|
|
|
.extend(other.variables.iter().map(|(k, v)| (k.clone(), v.clone())));
|
|
|
|
self.functions.extend(
|
|
|
|
other
|
|
|
|
.functions
|
|
|
|
.iter()
|
2021-12-06 11:12:54 +08:00
|
|
|
.filter(|&(_, f)| {
|
2021-03-12 14:11:08 +08:00
|
|
|
_filter(
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.namespace,
|
|
|
|
f.metadata.access,
|
2021-03-12 14:11:08 +08:00
|
|
|
f.func.is_script(),
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.name.as_str(),
|
|
|
|
f.metadata.params,
|
2021-03-12 14:11:08 +08:00
|
|
|
)
|
|
|
|
})
|
2020-10-25 00:39:47 +08:00
|
|
|
.map(|(&k, v)| (k, v.clone())),
|
|
|
|
);
|
2020-06-30 18:34:58 +08:00
|
|
|
|
2022-01-27 23:55:32 +08:00
|
|
|
self.type_iterators
|
|
|
|
.extend(other.type_iterators.iter().map(|(&k, v)| (k, v.clone())));
|
2020-06-30 18:34:58 +08:00
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
2020-11-16 14:07:48 +08:00
|
|
|
self.all_type_iterators.clear();
|
2020-06-30 18:34:58 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-06-30 18:34:58 +08:00
|
|
|
}
|
|
|
|
|
2020-11-17 12:23:53 +08:00
|
|
|
/// Filter out the functions, retaining only some script-defined functions based on a filter predicate.
|
2020-07-04 16:21:15 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline]
|
2020-11-17 12:23:53 +08:00
|
|
|
pub(crate) fn retain_script_functions(
|
2020-07-12 11:46:53 +08:00
|
|
|
&mut self,
|
2021-02-13 10:56:09 +08:00
|
|
|
filter: impl Fn(FnNamespace, FnAccess, &str, usize) -> bool,
|
2020-07-12 11:46:53 +08:00
|
|
|
) -> &mut Self {
|
2021-04-17 15:15:54 +08:00
|
|
|
self.functions = std::mem::take(&mut self.functions)
|
2021-03-23 12:13:53 +08:00
|
|
|
.into_iter()
|
|
|
|
.filter(|(_, f)| {
|
|
|
|
if f.func.is_script() {
|
2022-01-13 19:07:56 +08:00
|
|
|
filter(
|
|
|
|
f.metadata.namespace,
|
|
|
|
f.metadata.access,
|
|
|
|
f.metadata.name.as_str(),
|
|
|
|
f.metadata.params,
|
|
|
|
)
|
2021-03-23 12:13:53 +08:00
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
2020-06-30 18:34:58 +08:00
|
|
|
|
|
|
|
self.all_functions.clear();
|
|
|
|
self.all_variables.clear();
|
2020-11-16 14:07:48 +08:00
|
|
|
self.all_type_iterators.clear();
|
2020-06-30 18:34:58 +08:00
|
|
|
self.indexed = false;
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = false;
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-06-05 15:14:42 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get the number of variables, functions and type iterators in the [`Module`].
|
2020-10-08 22:25:50 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-10-05 21:52:39 +08:00
|
|
|
pub fn count(&self) -> (usize, usize, usize) {
|
|
|
|
(
|
|
|
|
self.variables.len(),
|
2020-11-09 22:44:20 +08:00
|
|
|
self.functions.len(),
|
|
|
|
self.type_iterators.len(),
|
2020-10-05 21:52:39 +08:00
|
|
|
)
|
2020-06-05 15:14:42 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get an iterator to the sub-modules in the [`Module`].
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-12-21 13:21:29 +08:00
|
|
|
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, &Shared<Module>)> {
|
|
|
|
self.modules.iter().map(|(k, m)| (k.as_str(), m))
|
2020-11-23 19:11:32 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get an iterator to the variables in the [`Module`].
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2020-11-23 19:11:32 +08:00
|
|
|
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
|
|
|
|
self.variables.iter().map(|(k, v)| (k.as_str(), v))
|
2020-06-05 15:14:42 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get an iterator to the functions in the [`Module`].
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-01-18 10:56:42 +08:00
|
|
|
#[allow(dead_code)]
|
2020-09-25 18:07:39 +08:00
|
|
|
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
|
2021-03-12 14:11:08 +08:00
|
|
|
self.functions.values().map(Box::as_ref)
|
2020-06-05 15:14:42 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
2020-10-05 21:52:39 +08:00
|
|
|
///
|
|
|
|
/// Function metadata includes:
|
2020-11-20 16:52:28 +08:00
|
|
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
|
|
|
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
|
|
|
|
/// 3) Function name (as string slice).
|
|
|
|
/// 4) Number of parameters.
|
2020-11-25 09:36:06 +08:00
|
|
|
/// 5) Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef].
|
2020-07-04 16:21:15 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-02-09 14:22:55 +08:00
|
|
|
pub(crate) fn iter_script_fn(
|
|
|
|
&self,
|
2021-03-12 14:11:08 +08:00
|
|
|
) -> impl Iterator<
|
|
|
|
Item = (
|
|
|
|
FnNamespace,
|
|
|
|
FnAccess,
|
|
|
|
&str,
|
|
|
|
usize,
|
|
|
|
&Shared<crate::ast::ScriptFnDef>,
|
|
|
|
),
|
|
|
|
> + '_ {
|
2021-12-06 11:12:54 +08:00
|
|
|
self.iter_fn().filter(|&f| f.func.is_script()).map(|f| {
|
|
|
|
(
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.namespace,
|
|
|
|
f.metadata.access,
|
|
|
|
f.metadata.name.as_str(),
|
|
|
|
f.metadata.params,
|
2021-12-17 16:07:13 +08:00
|
|
|
f.func.get_script_fn_def().expect("script-defined function"),
|
2021-12-06 11:12:54 +08:00
|
|
|
)
|
|
|
|
})
|
2020-09-24 16:10:25 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
2020-10-05 21:52:39 +08:00
|
|
|
///
|
|
|
|
/// Function metadata includes:
|
2020-11-20 16:52:28 +08:00
|
|
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
|
|
|
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
|
|
|
|
/// 3) Function name (as string slice).
|
|
|
|
/// 4) Number of parameters.
|
2020-10-05 21:52:39 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
#[cfg(not(feature = "internals"))]
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2020-11-17 12:23:53 +08:00
|
|
|
pub fn iter_script_fn_info(
|
|
|
|
&self,
|
|
|
|
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize)> {
|
2022-01-13 19:07:56 +08:00
|
|
|
self.iter_fn().filter(|&f| f.func.is_script()).map(|f| {
|
|
|
|
(
|
|
|
|
f.metadata.namespace,
|
|
|
|
f.metadata.access,
|
|
|
|
f.metadata.name.as_str(),
|
|
|
|
f.metadata.params,
|
|
|
|
)
|
|
|
|
})
|
2020-10-05 21:52:39 +08:00
|
|
|
}
|
|
|
|
|
2021-07-25 22:56:05 +08:00
|
|
|
/// _(internals)_ Get an iterator over all script-defined functions in the [`Module`].
|
2021-02-21 14:26:31 +08:00
|
|
|
/// Exported under the `internals` feature only.
|
2020-10-05 21:52:39 +08:00
|
|
|
///
|
|
|
|
/// Function metadata includes:
|
2020-11-20 16:52:28 +08:00
|
|
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
|
|
|
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
|
|
|
|
/// 3) Function name (as string slice).
|
|
|
|
/// 4) Number of parameters.
|
2021-07-25 22:56:05 +08:00
|
|
|
/// 5) _(internals)_ Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef].
|
2020-10-05 21:52:39 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-10-05 21:52:39 +08:00
|
|
|
pub fn iter_script_fn_info(
|
|
|
|
&self,
|
2021-03-12 19:33:22 +08:00
|
|
|
) -> impl Iterator<
|
|
|
|
Item = (
|
|
|
|
FnNamespace,
|
|
|
|
FnAccess,
|
|
|
|
&str,
|
|
|
|
usize,
|
|
|
|
&Shared<crate::ast::ScriptFnDef>,
|
|
|
|
),
|
|
|
|
> {
|
2020-10-05 21:52:39 +08:00
|
|
|
self.iter_script_fn()
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Create a new [`Module`] by evaluating an [`AST`][crate::AST].
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
2020-11-20 16:52:28 +08:00
|
|
|
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions
|
2020-10-03 11:42:54 +08:00
|
|
|
/// to cross-call each other. Functions in the global namespace, plus all functions
|
2021-01-02 23:30:10 +08:00
|
|
|
/// defined in the [`Module`], are _merged_ into a _unified_ namespace before each call.
|
2020-10-03 11:42:54 +08:00
|
|
|
/// Therefore, all functions will be found.
|
2020-09-25 18:07:39 +08:00
|
|
|
///
|
2020-10-27 11:30:38 +08:00
|
|
|
/// # Example
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
2020-05-08 22:38:56 +08:00
|
|
|
/// use rhai::{Engine, Module, Scope};
|
2020-05-06 19:45:17 +08:00
|
|
|
///
|
|
|
|
/// let engine = Engine::new();
|
2020-05-08 22:38:56 +08:00
|
|
|
/// let ast = engine.compile("let answer = 42; export answer;")?;
|
2020-10-03 11:42:54 +08:00
|
|
|
/// let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
|
2020-05-06 19:45:17 +08:00
|
|
|
/// assert!(module.contains_var("answer"));
|
2021-08-26 23:58:41 +08:00
|
|
|
/// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
|
2020-05-06 19:45:17 +08:00
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
2020-05-13 19:21:42 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2022-01-28 18:59:18 +08:00
|
|
|
#[inline(always)]
|
2020-10-18 17:02:17 +08:00
|
|
|
pub fn eval_ast_as_new(
|
2021-11-16 13:15:43 +08:00
|
|
|
scope: crate::Scope,
|
2020-11-16 16:28:04 +08:00
|
|
|
ast: &crate::AST,
|
|
|
|
engine: &crate::Engine,
|
2021-12-25 23:49:14 +08:00
|
|
|
) -> RhaiResultOf<Self> {
|
2022-01-28 18:59:18 +08:00
|
|
|
let global = &mut crate::eval::GlobalRuntimeState::new(engine);
|
2022-01-24 17:04:40 +08:00
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
Self::eval_ast_as_new_raw(engine, scope, global, ast)
|
|
|
|
}
|
|
|
|
/// Create a new [`Module`] by evaluating an [`AST`][crate::AST].
|
|
|
|
///
|
|
|
|
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions
|
|
|
|
/// to cross-call each other. Functions in the global namespace, plus all functions
|
|
|
|
/// defined in the [`Module`], are _merged_ into a _unified_ namespace before each call.
|
|
|
|
/// Therefore, all functions will be found.
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
|
|
|
pub(crate) fn eval_ast_as_new_raw(
|
|
|
|
engine: &crate::Engine,
|
|
|
|
scope: crate::Scope,
|
|
|
|
global: &mut crate::eval::GlobalRuntimeState,
|
|
|
|
ast: &crate::AST,
|
|
|
|
) -> RhaiResultOf<Self> {
|
|
|
|
let mut scope = scope;
|
2022-01-24 17:04:40 +08:00
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
// Save global state
|
2022-01-24 17:04:40 +08:00
|
|
|
let orig_imports_len = global.num_imports();
|
2022-01-28 18:59:18 +08:00
|
|
|
let orig_source = global.source.clone();
|
|
|
|
let orig_constants = std::mem::take(&mut global.constants);
|
2020-06-27 23:56:24 +08:00
|
|
|
|
2020-05-06 19:45:17 +08:00
|
|
|
// Run the script
|
2022-01-28 18:59:18 +08:00
|
|
|
let result = engine.eval_ast_with_scope_raw(&mut scope, global, &ast, 0);
|
2020-05-06 19:45:17 +08:00
|
|
|
|
|
|
|
// Create new module
|
2022-01-28 18:59:18 +08:00
|
|
|
let mut module = Module::new();
|
2020-06-27 23:56:24 +08:00
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
// Extra modules left become sub-modules
|
2022-01-07 12:19:01 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-12-28 11:42:52 +08:00
|
|
|
let mut func_global = None;
|
2020-11-15 23:14:16 +08:00
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
if result.is_ok() {
|
|
|
|
global
|
|
|
|
.scan_imports_raw()
|
|
|
|
.skip(orig_imports_len)
|
|
|
|
.for_each(|(k, m)| {
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
if func_global.is_none() {
|
|
|
|
func_global = Some(StaticVec::new());
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
func_global
|
|
|
|
.as_mut()
|
|
|
|
.expect("`Some`")
|
|
|
|
.push((k.clone(), m.clone()));
|
|
|
|
|
|
|
|
module.set_sub_module(k.clone(), m.clone());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore global state
|
|
|
|
global.constants = orig_constants;
|
|
|
|
global.truncate_imports(orig_imports_len);
|
|
|
|
global.source = orig_source;
|
2022-01-07 12:19:01 +08:00
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
result?;
|
|
|
|
|
|
|
|
// Variables with an alias left in the scope become module variables
|
|
|
|
for (_, value, mut aliases) in scope {
|
|
|
|
match aliases.len() {
|
|
|
|
0 => (),
|
|
|
|
1 => {
|
|
|
|
let alias = aliases.pop().unwrap();
|
|
|
|
module.set_var(alias, value);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let last_alias = aliases.pop().unwrap();
|
|
|
|
for alias in aliases {
|
|
|
|
module.set_var(alias, value.clone());
|
|
|
|
}
|
|
|
|
// Avoid cloning the last value
|
|
|
|
module.set_var(last_alias, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-28 11:42:52 +08:00
|
|
|
|
2022-01-07 12:19:01 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-12-28 11:42:52 +08:00
|
|
|
let func_global = func_global.map(|v| v.into_boxed_slice());
|
2020-05-06 19:45:17 +08:00
|
|
|
|
2020-10-13 09:38:14 +08:00
|
|
|
// Non-private functions defined become module functions
|
2020-09-25 18:07:39 +08:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-11-29 09:43:35 +08:00
|
|
|
if ast.has_functions() {
|
2021-11-28 22:57:28 +08:00
|
|
|
ast.shared_lib()
|
2021-12-06 11:12:54 +08:00
|
|
|
.iter_fn()
|
2022-01-13 19:07:56 +08:00
|
|
|
.filter(|&f| match f.metadata.access {
|
2021-11-27 14:24:36 +08:00
|
|
|
FnAccess::Public => true,
|
|
|
|
FnAccess::Private => false,
|
|
|
|
})
|
2021-12-06 11:12:54 +08:00
|
|
|
.filter(|&f| f.func.is_script())
|
2021-11-27 14:24:36 +08:00
|
|
|
.for_each(|f| {
|
|
|
|
// Encapsulate AST environment
|
|
|
|
let mut func = f
|
|
|
|
.func
|
|
|
|
.get_script_fn_def()
|
2021-12-17 16:07:13 +08:00
|
|
|
.expect("script-defined function")
|
2021-11-27 14:24:36 +08:00
|
|
|
.as_ref()
|
|
|
|
.clone();
|
2021-11-28 22:57:28 +08:00
|
|
|
func.lib = Some(ast.shared_lib().clone());
|
2021-12-27 23:03:30 +08:00
|
|
|
func.global = func_global.clone();
|
2021-11-27 14:24:36 +08:00
|
|
|
module.set_script_fn(func);
|
|
|
|
});
|
|
|
|
}
|
2020-05-06 19:45:17 +08:00
|
|
|
|
2022-01-01 17:20:00 +08:00
|
|
|
module.set_id(ast.source_raw().clone());
|
2021-06-28 13:53:30 +08:00
|
|
|
|
2020-11-21 22:18:32 +08:00
|
|
|
module.build_index();
|
|
|
|
|
2020-05-06 19:45:17 +08:00
|
|
|
Ok(module)
|
|
|
|
}
|
2020-05-08 00:19:08 +08:00
|
|
|
|
2021-03-05 20:07:35 +08:00
|
|
|
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the [`Module`] is not yet indexed via [`build_index`][Module::build_index].
|
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-03-05 20:07:35 +08:00
|
|
|
pub fn contains_indexed_global_functions(&self) -> bool {
|
|
|
|
self.contains_indexed_global_functions
|
2021-03-03 11:40:27 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Scan through all the sub-modules in the [`Module`] and build a hash index of all
|
2020-11-08 14:29:54 +08:00
|
|
|
/// variables and functions as one flattened namespace.
|
|
|
|
///
|
2021-01-02 23:30:10 +08:00
|
|
|
/// If the [`Module`] is already indexed, this method has no effect.
|
2020-11-21 22:18:32 +08:00
|
|
|
pub fn build_index(&mut self) -> &mut Self {
|
2020-05-08 00:19:08 +08:00
|
|
|
// Collect a particular module.
|
2020-05-09 10:00:59 +08:00
|
|
|
fn index_module<'a>(
|
2020-05-17 22:19:49 +08:00
|
|
|
module: &'a Module,
|
2021-03-12 22:30:08 +08:00
|
|
|
path: &mut Vec<&'a str>,
|
2021-03-23 12:13:53 +08:00
|
|
|
variables: &mut BTreeMap<u64, Dynamic>,
|
2021-05-03 13:45:41 +08:00
|
|
|
functions: &mut BTreeMap<u64, Shared<CallableFunction>>,
|
2022-01-27 23:55:32 +08:00
|
|
|
type_iterators: &mut BTreeMap<TypeId, Shared<IteratorFn>>,
|
2021-03-05 20:07:35 +08:00
|
|
|
) -> bool {
|
|
|
|
let mut contains_indexed_global_functions = false;
|
|
|
|
|
2022-01-28 18:59:18 +08:00
|
|
|
for (name, m) in &module.modules {
|
2020-05-09 10:00:59 +08:00
|
|
|
// Index all the sub-modules first.
|
2021-03-12 22:30:08 +08:00
|
|
|
path.push(name);
|
|
|
|
if index_module(m, path, variables, functions, type_iterators) {
|
2021-03-05 20:07:35 +08:00
|
|
|
contains_indexed_global_functions = true;
|
|
|
|
}
|
2021-03-12 22:30:08 +08:00
|
|
|
path.pop();
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-05-08 00:19:08 +08:00
|
|
|
|
2020-05-09 10:00:59 +08:00
|
|
|
// Index all variables
|
2022-01-28 18:59:18 +08:00
|
|
|
for (var_name, value) in &module.variables {
|
2021-07-24 14:11:16 +08:00
|
|
|
let hash_var = crate::calc_qualified_var_hash(path.iter().copied(), var_name);
|
2020-11-16 14:07:48 +08:00
|
|
|
variables.insert(hash_var, value.clone());
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-11-16 14:07:48 +08:00
|
|
|
|
|
|
|
// Index type iterators
|
2022-01-28 18:59:18 +08:00
|
|
|
for (&type_id, func) in &module.type_iterators {
|
2022-01-27 23:55:32 +08:00
|
|
|
type_iterators.insert(type_id, func.clone());
|
2021-03-05 20:07:35 +08:00
|
|
|
contains_indexed_global_functions = true;
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2020-11-16 14:07:48 +08:00
|
|
|
|
2020-05-09 10:00:59 +08:00
|
|
|
// Index all Rust functions
|
2022-01-28 18:59:18 +08:00
|
|
|
for (&hash, f) in &module.functions {
|
2022-01-13 19:07:56 +08:00
|
|
|
match f.metadata.namespace {
|
2021-03-12 14:11:08 +08:00
|
|
|
FnNamespace::Global => {
|
|
|
|
// Flatten all functions with global namespace
|
|
|
|
functions.insert(hash, f.func.clone());
|
|
|
|
contains_indexed_global_functions = true;
|
2021-03-03 11:40:27 +08:00
|
|
|
}
|
2021-03-12 14:11:08 +08:00
|
|
|
FnNamespace::Internal => (),
|
|
|
|
}
|
2022-01-13 19:07:56 +08:00
|
|
|
match f.metadata.access {
|
2021-03-12 14:11:08 +08:00
|
|
|
FnAccess::Public => (),
|
2022-01-28 18:59:18 +08:00
|
|
|
FnAccess::Private => continue, // Do not index private functions
|
2021-03-12 14:11:08 +08:00
|
|
|
}
|
2021-03-03 11:40:27 +08:00
|
|
|
|
2021-03-12 14:11:08 +08:00
|
|
|
if !f.func.is_script() {
|
2022-01-13 19:07:56 +08:00
|
|
|
let hash_qualified_fn = calc_native_fn_hash(
|
|
|
|
path.iter().cloned(),
|
|
|
|
f.metadata.name.as_str(),
|
|
|
|
&f.param_types,
|
|
|
|
);
|
2021-03-12 14:11:08 +08:00
|
|
|
functions.insert(hash_qualified_fn, f.func.clone());
|
|
|
|
} else if cfg!(not(feature = "no_function")) {
|
2021-05-19 20:26:11 +08:00
|
|
|
let hash_qualified_script = crate::calc_qualified_fn_hash(
|
|
|
|
path.iter().cloned(),
|
2022-01-13 19:07:56 +08:00
|
|
|
f.metadata.name.as_str(),
|
|
|
|
f.metadata.params,
|
2021-05-19 20:26:11 +08:00
|
|
|
);
|
2021-03-12 14:11:08 +08:00
|
|
|
functions.insert(hash_qualified_script, f.func.clone());
|
|
|
|
}
|
2022-01-28 18:59:18 +08:00
|
|
|
}
|
2021-03-05 20:07:35 +08:00
|
|
|
|
|
|
|
contains_indexed_global_functions
|
2020-06-27 23:56:24 +08:00
|
|
|
}
|
|
|
|
|
2020-10-01 23:31:27 +08:00
|
|
|
if !self.indexed {
|
2021-03-12 22:30:08 +08:00
|
|
|
let mut path = Vec::with_capacity(4);
|
2021-11-07 18:12:37 +08:00
|
|
|
let mut variables = BTreeMap::new();
|
|
|
|
let mut functions = BTreeMap::new();
|
|
|
|
let mut type_iterators = BTreeMap::new();
|
2020-07-26 15:53:22 +08:00
|
|
|
|
2021-04-17 22:19:48 +08:00
|
|
|
path.push("");
|
2020-05-19 19:03:06 +08:00
|
|
|
|
2021-03-05 20:07:35 +08:00
|
|
|
self.contains_indexed_global_functions = index_module(
|
2020-11-16 14:07:48 +08:00
|
|
|
self,
|
2021-03-12 22:30:08 +08:00
|
|
|
&mut path,
|
2020-11-16 14:07:48 +08:00
|
|
|
&mut variables,
|
|
|
|
&mut functions,
|
|
|
|
&mut type_iterators,
|
|
|
|
);
|
|
|
|
|
|
|
|
self.all_variables = variables;
|
|
|
|
self.all_functions = functions;
|
|
|
|
self.all_type_iterators = type_iterators;
|
2020-10-01 23:31:27 +08:00
|
|
|
self.indexed = true;
|
|
|
|
}
|
2020-11-21 22:18:32 +08:00
|
|
|
|
|
|
|
self
|
2020-05-08 00:19:08 +08:00
|
|
|
}
|
2020-05-13 19:21:42 +08:00
|
|
|
|
2020-11-16 14:07:48 +08:00
|
|
|
/// Does a type iterator exist in the entire module tree?
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-11-16 14:07:48 +08:00
|
|
|
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
|
|
|
|
self.all_type_iterators.contains_key(&id)
|
|
|
|
}
|
|
|
|
|
2020-05-13 19:21:42 +08:00
|
|
|
/// Does a type iterator exist in the module?
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2020-05-13 20:22:05 +08:00
|
|
|
pub fn contains_iter(&self, id: TypeId) -> bool {
|
2020-05-13 19:21:42 +08:00
|
|
|
self.type_iterators.contains_key(&id)
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a type iterator into the [`Module`].
|
2022-01-27 23:55:32 +08:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-07-10 11:06:13 +08:00
|
|
|
#[inline]
|
2022-01-27 23:55:32 +08:00
|
|
|
pub fn set_iter(
|
|
|
|
&mut self,
|
|
|
|
type_id: TypeId,
|
|
|
|
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static,
|
|
|
|
) -> &mut Self {
|
|
|
|
let func = Shared::new(func);
|
|
|
|
if self.indexed {
|
|
|
|
self.all_type_iterators.insert(type_id, func.clone());
|
|
|
|
self.contains_indexed_global_functions = true;
|
|
|
|
}
|
|
|
|
self.type_iterators.insert(type_id, func);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set a type iterator into the [`Module`].
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
#[inline]
|
|
|
|
pub fn set_iter(
|
|
|
|
&mut self,
|
|
|
|
type_id: TypeId,
|
|
|
|
func: impl Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + SendSync + 'static,
|
|
|
|
) -> &mut Self {
|
|
|
|
let func = Shared::new(func);
|
2021-04-17 22:19:48 +08:00
|
|
|
if self.indexed {
|
2022-01-27 23:55:32 +08:00
|
|
|
self.all_type_iterators.insert(type_id, func.clone());
|
2021-04-17 22:19:48 +08:00
|
|
|
self.contains_indexed_global_functions = true;
|
|
|
|
}
|
|
|
|
self.type_iterators.insert(type_id, func);
|
2020-07-12 11:46:53 +08:00
|
|
|
self
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set a type iterator into the [`Module`].
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2020-10-15 22:11:18 +08:00
|
|
|
pub fn set_iterable<T>(&mut self) -> &mut Self
|
|
|
|
where
|
|
|
|
T: Variant + Clone + IntoIterator,
|
|
|
|
<T as IntoIterator>::Item: Variant + Clone,
|
|
|
|
{
|
2020-10-14 23:22:10 +08:00
|
|
|
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
|
|
|
|
Box::new(obj.cast::<T>().into_iter().map(Dynamic::from))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Set an iterator type into the [`Module`] as a type iterator.
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2020-10-15 22:11:18 +08:00
|
|
|
pub fn set_iterator<T>(&mut self) -> &mut Self
|
|
|
|
where
|
|
|
|
T: Variant + Clone + Iterator,
|
|
|
|
<T as Iterator>::Item: Variant + Clone,
|
|
|
|
{
|
2020-10-14 23:22:10 +08:00
|
|
|
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
|
|
|
|
Box::new(obj.cast::<T>().map(Dynamic::from))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-11-16 14:07:48 +08:00
|
|
|
/// Get the specified type iterator.
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2022-01-27 23:55:32 +08:00
|
|
|
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
|
|
|
self.all_type_iterators.get(&id).map(|f| f.as_ref())
|
2020-11-16 14:07:48 +08:00
|
|
|
}
|
|
|
|
|
2020-05-13 19:21:42 +08:00
|
|
|
/// Get the specified type iterator.
|
2021-10-21 17:26:43 +08:00
|
|
|
#[inline]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2022-01-27 23:55:32 +08:00
|
|
|
pub(crate) fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
|
|
|
|
self.type_iterators.get(&id).map(|f| f.as_ref())
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-24 17:04:40 +08:00
|
|
|
/// _(internals)_ A chain of [module][Module] names to namespace-qualify a variable or function call.
|
|
|
|
/// Exported under the `internals` feature only.
|
2020-07-25 15:52:27 +08:00
|
|
|
///
|
2021-12-27 23:03:30 +08:00
|
|
|
/// A [`u64`] offset to the current [stack of imported modules][crate::GlobalRuntimeState] is
|
|
|
|
/// cached for quick search purposes.
|
2020-05-13 19:21:42 +08:00
|
|
|
///
|
2021-12-27 23:03:30 +08:00
|
|
|
/// A [`StaticVec`] is used because the vast majority of namespace-qualified access contains only
|
|
|
|
/// one level, and it is wasteful to always allocate a [`Vec`] with one element.
|
2020-07-19 17:14:55 +08:00
|
|
|
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
2021-12-25 23:49:14 +08:00
|
|
|
pub struct Namespace {
|
2021-01-11 23:09:33 +08:00
|
|
|
index: Option<NonZeroUsize>,
|
|
|
|
path: StaticVec<Ident>,
|
|
|
|
}
|
2020-05-13 19:21:42 +08:00
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl fmt::Debug for Namespace {
|
2020-05-13 19:21:42 +08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-01-11 23:09:33 +08:00
|
|
|
if let Some(index) = self.index {
|
2021-03-09 14:00:21 +08:00
|
|
|
write!(f, "{} -> ", index)?;
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
2021-03-09 14:00:21 +08:00
|
|
|
|
|
|
|
f.write_str(
|
|
|
|
&self
|
|
|
|
.path
|
|
|
|
.iter()
|
|
|
|
.map(|Ident { name, .. }| name.as_str())
|
2021-06-06 12:17:04 +08:00
|
|
|
.collect::<StaticVec<_>>()
|
2021-10-27 23:30:25 +08:00
|
|
|
.join(Token::DoubleColon.literal_syntax()),
|
2021-03-09 14:00:21 +08:00
|
|
|
)
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl fmt::Display for Namespace {
|
2021-04-23 14:24:53 +08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-10-27 23:30:25 +08:00
|
|
|
f.write_str(
|
|
|
|
&self
|
|
|
|
.path
|
|
|
|
.iter()
|
|
|
|
.map(|Ident { name, .. }| name.as_str())
|
|
|
|
.collect::<StaticVec<_>>()
|
|
|
|
.join(Token::DoubleColon.literal_syntax()),
|
|
|
|
)
|
2021-04-23 14:24:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl Deref for Namespace {
|
2020-12-22 16:45:56 +08:00
|
|
|
type Target = StaticVec<Ident>;
|
2020-05-13 19:21:42 +08:00
|
|
|
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2020-05-13 19:21:42 +08:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2021-01-11 23:09:33 +08:00
|
|
|
&self.path
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl DerefMut for Namespace {
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2020-05-13 19:21:42 +08:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2021-01-11 23:09:33 +08:00
|
|
|
&mut self.path
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
2021-11-28 22:57:28 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl From<Vec<Ident>> for Namespace {
|
2021-11-28 22:57:28 +08:00
|
|
|
#[inline(always)]
|
|
|
|
fn from(mut path: Vec<Ident>) -> Self {
|
|
|
|
path.shrink_to_fit();
|
|
|
|
Self {
|
|
|
|
index: None,
|
|
|
|
path: path.into(),
|
|
|
|
}
|
|
|
|
}
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl From<StaticVec<Ident>> for Namespace {
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-10-21 17:26:43 +08:00
|
|
|
fn from(mut path: StaticVec<Ident>) -> Self {
|
2021-05-05 18:38:52 +08:00
|
|
|
path.shrink_to_fit();
|
2021-01-11 23:09:33 +08:00
|
|
|
Self { index: None, path }
|
2020-10-07 15:40:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 23:49:14 +08:00
|
|
|
impl Namespace {
|
|
|
|
/// Create a new [`Namespace`].
|
2021-07-04 16:40:15 +08:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
2021-11-25 17:09:00 +08:00
|
|
|
pub const fn new() -> Self {
|
2021-07-10 11:06:13 +08:00
|
|
|
Self {
|
|
|
|
index: None,
|
2021-11-25 17:09:00 +08:00
|
|
|
path: StaticVec::new_const(),
|
2021-07-10 11:06:13 +08:00
|
|
|
}
|
2021-07-04 16:40:15 +08:00
|
|
|
}
|
2020-12-24 23:22:50 +08:00
|
|
|
/// Get the [`Scope`][crate::Scope] index offset.
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2021-06-12 22:47:43 +08:00
|
|
|
#[must_use]
|
2021-06-28 18:06:05 +08:00
|
|
|
pub(crate) const fn index(&self) -> Option<NonZeroUsize> {
|
2021-01-11 23:09:33 +08:00
|
|
|
self.index
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
2020-12-24 23:22:50 +08:00
|
|
|
/// Set the [`Scope`][crate::Scope] index offset.
|
2020-10-18 22:10:08 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-03-10 13:32:09 +08:00
|
|
|
#[inline(always)]
|
2020-05-13 19:21:42 +08:00
|
|
|
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
|
2021-01-11 23:09:33 +08:00
|
|
|
self.index = index
|
2020-05-13 19:21:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
2020-09-25 10:59:21 +08:00
|
|
|
pub use resolvers::ModuleResolver;
|
2020-05-06 19:45:17 +08:00
|
|
|
|
2021-01-02 23:30:10 +08:00
|
|
|
/// Module containing all built-in [module resolvers][ModuleResolver].
|
2020-07-07 23:44:23 +08:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2020-09-25 10:59:21 +08:00
|
|
|
pub mod resolvers;
|