2020-07-23 12:40:42 +02:00
|
|
|
//! Module defining interfaces to native-Rust functions.
|
|
|
|
|
2021-11-13 15:36:23 +01:00
|
|
|
use super::call::FnCallArgs;
|
2021-12-20 15:13:00 +01:00
|
|
|
use crate::ast::FnCallHashes;
|
2022-04-16 10:36:53 +02:00
|
|
|
use crate::eval::{Caches, GlobalRuntimeState};
|
2020-07-26 10:10:38 +02:00
|
|
|
use crate::plugin::PluginFunction;
|
2022-12-27 15:51:38 +01:00
|
|
|
use crate::tokenizer::{is_valid_function_name, Token, TokenizeState};
|
2021-12-18 05:29:04 +01:00
|
|
|
use crate::types::dynamic::Variant;
|
2020-11-16 16:10:14 +01:00
|
|
|
use crate::{
|
2022-12-04 07:06:54 +01:00
|
|
|
calc_fn_hash, Dynamic, Engine, EvalContext, FuncArgs, Position, RhaiResult, RhaiResultOf,
|
|
|
|
StaticVec, VarDefInfo, ERR,
|
2020-11-16 16:10:14 +01:00
|
|
|
};
|
2022-11-21 16:42:29 +01:00
|
|
|
use std::any::{type_name, TypeId};
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
2020-07-26 04:03:59 +02:00
|
|
|
|
2020-06-18 12:39:28 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-05-21 11:11:01 +02:00
|
|
|
pub trait SendSync: Send + Sync {}
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-05-21 11:11:01 +02:00
|
|
|
impl<T: Send + Sync> SendSync for T {}
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-06-18 12:39:28 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-05-21 11:11:01 +02:00
|
|
|
pub trait SendSync {}
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-05-21 11:11:01 +02:00
|
|
|
impl<T> SendSync for T {}
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Immutable reference-counted container.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::rc::Rc as Shared;
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Immutable reference-counted container.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::sync::Arc as Shared;
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Synchronized shared object.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::cell::RefCell as Locked;
|
2021-11-08 04:35:46 +01:00
|
|
|
|
2022-03-03 06:02:57 +01:00
|
|
|
/// Read-only lock guard for synchronized shared object.
|
2021-11-08 04:35:46 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-03-03 06:02:57 +01:00
|
|
|
pub type LockGuard<'a, T> = std::cell::Ref<'a, T>;
|
|
|
|
|
|
|
|
/// Mutable lock guard for synchronized shared object.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
pub type LockGuardMut<'a, T> = std::cell::RefMut<'a, T>;
|
2021-11-08 04:35:46 +01:00
|
|
|
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Synchronized shared object.
|
|
|
|
#[cfg(feature = "sync")]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::sync::RwLock as Locked;
|
2020-10-16 17:41:56 +02:00
|
|
|
|
2022-03-03 06:02:57 +01:00
|
|
|
/// Read-only lock guard for synchronized shared object.
|
2021-11-08 04:35:46 +01:00
|
|
|
#[cfg(feature = "sync")]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2022-03-03 06:02:57 +01:00
|
|
|
pub type LockGuard<'a, T> = std::sync::RwLockReadGuard<'a, T>;
|
|
|
|
|
|
|
|
/// Mutable lock guard for synchronized shared object.
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub type LockGuardMut<'a, T> = std::sync::RwLockWriteGuard<'a, T>;
|
2021-11-08 04:35:46 +01:00
|
|
|
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Context of a native Rust function call.
|
2021-03-15 04:36:30 +01:00
|
|
|
#[derive(Debug)]
|
2021-03-03 15:49:57 +01:00
|
|
|
pub struct NativeCallContext<'a> {
|
2022-01-02 08:14:55 +01:00
|
|
|
/// The current [`Engine`].
|
2021-03-03 15:49:57 +01:00
|
|
|
engine: &'a Engine,
|
2022-01-02 08:14:55 +01:00
|
|
|
/// Name of function called.
|
2021-03-03 15:49:57 +01:00
|
|
|
fn_name: &'a str,
|
2022-01-02 08:14:55 +01:00
|
|
|
/// Function source, if any.
|
2021-03-03 15:49:57 +01:00
|
|
|
source: Option<&'a str>,
|
2022-01-02 08:14:55 +01:00
|
|
|
/// The current [`GlobalRuntimeState`], if any.
|
2022-11-08 14:28:20 +01:00
|
|
|
global: &'a GlobalRuntimeState,
|
2022-01-02 08:14:55 +01:00
|
|
|
/// [Position] of the function call.
|
2021-11-05 12:35:33 +01:00
|
|
|
pos: Position,
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
|
2022-11-07 09:19:10 +01:00
|
|
|
/// _(internals)_ Context of a native Rust function call.
|
|
|
|
/// Exported under the `internals` feature only.
|
2022-11-09 05:44:57 +01:00
|
|
|
///
|
|
|
|
/// # WARNING - Volatile Type
|
|
|
|
///
|
|
|
|
/// This type is volatile and may change in the future.
|
|
|
|
#[deprecated = "This type is NOT deprecated, but it is considered volatile and may change in the future."]
|
2022-11-07 09:19:10 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct NativeCallContextStore {
|
|
|
|
/// Name of function called.
|
|
|
|
pub fn_name: String,
|
|
|
|
/// Function source, if any.
|
|
|
|
pub source: Option<String>,
|
|
|
|
/// The current [`GlobalRuntimeState`], if any.
|
|
|
|
pub global: GlobalRuntimeState,
|
|
|
|
/// [Position] of the function call.
|
|
|
|
pub pos: Position,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "internals")]
|
2022-11-09 05:44:57 +01:00
|
|
|
#[allow(deprecated)]
|
2022-11-07 09:19:10 +01:00
|
|
|
impl NativeCallContextStore {
|
2022-11-11 09:46:28 +01:00
|
|
|
/// Create a [`NativeCallContext`] from a [`NativeCallContextStore`].
|
2022-11-09 05:44:57 +01:00
|
|
|
///
|
|
|
|
/// # WARNING - Unstable API
|
|
|
|
///
|
|
|
|
/// This API is volatile and may change in the future.
|
|
|
|
#[deprecated = "This API is NOT deprecated, but it is considered volatile and may change in the future."]
|
2022-11-07 09:19:10 +01:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub fn create_context<'a>(&'a self, engine: &'a Engine) -> NativeCallContext<'a> {
|
|
|
|
NativeCallContext::from_stored_data(engine, self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-20 09:31:57 +02:00
|
|
|
impl<'a>
|
2021-11-05 12:35:33 +01:00
|
|
|
From<(
|
|
|
|
&'a Engine,
|
2022-10-20 09:31:57 +02:00
|
|
|
&'a str,
|
|
|
|
Option<&'a str>,
|
2022-11-07 09:19:10 +01:00
|
|
|
&'a GlobalRuntimeState,
|
2021-11-05 12:35:33 +01:00
|
|
|
Position,
|
|
|
|
)> for NativeCallContext<'a>
|
2020-11-07 16:33:21 +01:00
|
|
|
{
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2021-11-05 12:35:33 +01:00
|
|
|
fn from(
|
|
|
|
value: (
|
|
|
|
&'a Engine,
|
2022-10-20 09:31:57 +02:00
|
|
|
&'a str,
|
|
|
|
Option<&'a str>,
|
2021-12-27 16:03:30 +01:00
|
|
|
&'a GlobalRuntimeState,
|
2021-11-05 12:35:33 +01:00
|
|
|
Position,
|
|
|
|
),
|
|
|
|
) -> Self {
|
2020-11-07 16:33:21 +01:00
|
|
|
Self {
|
|
|
|
engine: value.0,
|
2022-10-20 09:31:57 +02:00
|
|
|
fn_name: value.1,
|
|
|
|
source: value.2,
|
2022-11-08 14:28:20 +01:00
|
|
|
global: value.3,
|
2022-11-10 04:49:10 +01:00
|
|
|
pos: value.4,
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 15:49:57 +01:00
|
|
|
impl<'a> NativeCallContext<'a> {
|
2021-07-25 16:56:05 +02:00
|
|
|
/// _(internals)_ Create a new [`NativeCallContext`].
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2020-11-08 11:15:23 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2022-11-23 06:24:14 +01:00
|
|
|
pub const fn new_with_all_fields(
|
2021-03-03 15:49:57 +01:00
|
|
|
engine: &'a Engine,
|
2022-10-20 09:31:57 +02:00
|
|
|
fn_name: &'a str,
|
|
|
|
source: Option<&'a str>,
|
2021-12-27 16:03:30 +01:00
|
|
|
global: &'a GlobalRuntimeState,
|
2021-11-05 12:35:33 +01:00
|
|
|
pos: Position,
|
2020-11-08 11:15:23 +01:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
engine,
|
2022-10-20 09:31:57 +02:00
|
|
|
fn_name,
|
|
|
|
source,
|
2022-11-08 14:28:20 +01:00
|
|
|
global,
|
2021-11-05 12:35:33 +01:00
|
|
|
pos,
|
2020-11-08 11:15:23 +01:00
|
|
|
}
|
|
|
|
}
|
2022-11-07 09:19:10 +01:00
|
|
|
|
2022-11-11 09:46:28 +01:00
|
|
|
/// _(internals)_ Create a [`NativeCallContext`] from a [`NativeCallContextStore`].
|
2022-11-07 09:19:10 +01:00
|
|
|
/// Exported under the `internals` feature only.
|
2022-11-09 05:44:57 +01:00
|
|
|
///
|
|
|
|
/// # WARNING - Unstable API
|
|
|
|
///
|
|
|
|
/// This API is volatile and may change in the future.
|
|
|
|
#[deprecated = "This API is NOT deprecated, but it is considered volatile and may change in the future."]
|
2022-11-07 09:19:10 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
2022-11-09 05:44:57 +01:00
|
|
|
#[allow(deprecated)]
|
2022-11-07 09:19:10 +01:00
|
|
|
pub fn from_stored_data(engine: &'a Engine, context: &'a NativeCallContextStore) -> Self {
|
|
|
|
Self {
|
|
|
|
engine,
|
|
|
|
fn_name: &context.fn_name,
|
2022-11-25 02:46:13 +01:00
|
|
|
source: context.source.as_deref(),
|
2022-11-08 14:28:20 +01:00
|
|
|
global: &context.global,
|
2022-11-07 09:19:10 +01:00
|
|
|
pos: context.pos,
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 09:46:28 +01:00
|
|
|
/// _(internals)_ Store this [`NativeCallContext`] into a [`NativeCallContextStore`].
|
2022-11-07 09:19:10 +01:00
|
|
|
/// Exported under the `internals` feature only.
|
2022-11-09 05:44:57 +01:00
|
|
|
///
|
|
|
|
/// # WARNING - Unstable API
|
|
|
|
///
|
|
|
|
/// This API is volatile and may change in the future.
|
|
|
|
#[deprecated = "This API is NOT deprecated, but it is considered volatile and may change in the future."]
|
2022-11-07 09:19:10 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
2022-11-09 05:44:57 +01:00
|
|
|
#[allow(deprecated)]
|
2022-11-07 09:19:10 +01:00
|
|
|
pub fn store_data(&self) -> NativeCallContextStore {
|
|
|
|
NativeCallContextStore {
|
|
|
|
fn_name: self.fn_name.to_string(),
|
2022-12-22 10:34:58 +01:00
|
|
|
source: self.source.map(ToString::to_string),
|
2022-11-08 14:28:20 +01:00
|
|
|
global: self.global.clone(),
|
2022-11-07 09:19:10 +01:00
|
|
|
pos: self.pos,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// The current [`Engine`].
|
2020-10-18 11:02:17 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn engine(&self) -> &Engine {
|
2020-10-18 11:02:17 +02:00
|
|
|
self.engine
|
|
|
|
}
|
2021-01-21 14:49:25 +01:00
|
|
|
/// Name of the function called.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn fn_name(&self) -> &str {
|
2021-01-21 14:49:25 +01:00
|
|
|
self.fn_name
|
|
|
|
}
|
2022-01-02 08:14:55 +01:00
|
|
|
/// [Position] of the function call.
|
2021-11-05 12:35:33 +01:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub const fn position(&self) -> Position {
|
|
|
|
self.pos
|
|
|
|
}
|
2022-02-02 07:47:35 +01:00
|
|
|
/// Current nesting level of function calls.
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub const fn call_level(&self) -> usize {
|
2022-11-08 14:28:20 +01:00
|
|
|
self.global.level
|
2022-02-02 07:47:35 +01:00
|
|
|
}
|
2020-12-21 16:12:45 +01:00
|
|
|
/// The current source.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn source(&self) -> Option<&str> {
|
2020-12-21 16:12:45 +01:00
|
|
|
self.source
|
|
|
|
}
|
2022-05-01 18:03:45 +02:00
|
|
|
/// Custom state kept in a [`Dynamic`].
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
2022-11-23 06:24:14 +01:00
|
|
|
pub const fn tag(&self) -> Option<&Dynamic> {
|
2022-11-08 14:28:20 +01:00
|
|
|
Some(&self.global.tag)
|
2022-05-01 18:03:45 +02:00
|
|
|
}
|
2021-12-28 04:42:52 +01:00
|
|
|
/// Get an iterator over the current set of modules imported via `import` statements
|
|
|
|
/// in reverse order.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2021-01-01 10:05:06 +01:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2022-11-19 11:57:15 +01:00
|
|
|
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &crate::Module)> {
|
2022-11-08 14:28:20 +01:00
|
|
|
self.global.iter_imports()
|
2021-01-01 10:05:06 +01:00
|
|
|
}
|
2021-12-28 04:42:52 +01:00
|
|
|
/// Get an iterator over the current set of modules imported via `import` statements in reverse order.
|
2021-03-03 15:49:57 +01:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-03-07 15:10:54 +01:00
|
|
|
#[allow(dead_code)]
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-03-31 04:16:38 +02:00
|
|
|
pub(crate) fn iter_imports_raw(
|
|
|
|
&self,
|
2022-11-19 11:57:15 +01:00
|
|
|
) -> impl Iterator<Item = (&crate::ImmutableString, &crate::SharedModule)> {
|
2022-11-08 14:28:20 +01:00
|
|
|
self.global.iter_imports_raw()
|
2021-03-03 15:49:57 +01:00
|
|
|
}
|
2022-01-02 08:14:55 +01:00
|
|
|
/// _(internals)_ The current [`GlobalRuntimeState`], if any.
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2020-11-07 16:33:21 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2022-11-08 14:28:20 +01:00
|
|
|
pub const fn global_runtime_state(&self) -> &GlobalRuntimeState {
|
2021-12-27 16:03:30 +01:00
|
|
|
self.global
|
2020-11-07 16:33:21 +01:00
|
|
|
}
|
2022-12-11 10:18:14 +01:00
|
|
|
/// _(internals)_ The current [`GlobalRuntimeState`], if any.
|
|
|
|
#[cfg(not(feature = "internals"))]
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub(crate) const fn global_runtime_state(&self) -> &GlobalRuntimeState {
|
|
|
|
self.global
|
|
|
|
}
|
2021-12-28 04:42:52 +01:00
|
|
|
/// Get an iterator over the namespaces containing definitions of all script-defined functions
|
2022-08-26 10:20:23 +02:00
|
|
|
/// in reverse order (i.e. parent namespaces are iterated after child namespaces).
|
2022-11-10 07:25:48 +01:00
|
|
|
///
|
|
|
|
/// Not available under `no_function`.
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2022-11-19 11:57:15 +01:00
|
|
|
pub fn iter_namespaces(&self) -> impl Iterator<Item = &crate::Module> {
|
2022-11-23 06:24:14 +01:00
|
|
|
self.global.lib.iter().map(AsRef::as_ref)
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
2022-08-26 10:20:23 +02:00
|
|
|
/// _(internals)_ The current stack of namespaces containing definitions of all script-defined functions.
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2022-11-10 07:25:48 +01:00
|
|
|
///
|
|
|
|
/// Not available under `no_function`.
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-01-01 10:05:06 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2022-11-19 11:57:15 +01:00
|
|
|
pub fn namespaces(&self) -> &[crate::SharedModule] {
|
2022-11-10 04:49:10 +01:00
|
|
|
&self.global.lib
|
2021-01-01 10:05:06 +01:00
|
|
|
}
|
2021-12-18 05:29:04 +01:00
|
|
|
/// Call a function inside the call context with the provided arguments.
|
|
|
|
#[inline]
|
|
|
|
pub fn call_fn<T: Variant + Clone>(
|
|
|
|
&self,
|
|
|
|
fn_name: impl AsRef<str>,
|
|
|
|
args: impl FuncArgs,
|
2021-12-25 16:49:14 +01:00
|
|
|
) -> RhaiResultOf<T> {
|
2021-12-18 05:29:04 +01:00
|
|
|
let mut arg_values = StaticVec::new_const();
|
|
|
|
args.parse(&mut arg_values);
|
|
|
|
|
|
|
|
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
self._call_fn_raw(fn_name, &mut args, false, false, false)
|
|
|
|
.and_then(|result| {
|
|
|
|
// Bail out early if the return type needs no cast
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2022-12-09 09:41:01 +01:00
|
|
|
return Ok(reify! { result => T });
|
2022-12-09 03:04:44 +01:00
|
|
|
}
|
2022-10-14 10:57:14 +02:00
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
let typ = self.engine().map_type_name(result.type_name());
|
2022-10-14 10:57:14 +02:00
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
result.try_cast().ok_or_else(|| {
|
|
|
|
let t = self.engine().map_type_name(type_name::<T>()).into();
|
|
|
|
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
|
|
|
})
|
|
|
|
})
|
2022-10-14 10:57:14 +02:00
|
|
|
}
|
|
|
|
/// Call a registered native Rust function inside the call context with the provided arguments.
|
|
|
|
///
|
|
|
|
/// This is often useful because Rust functions typically only want to cross-call other
|
|
|
|
/// registered Rust functions and not have to worry about scripted functions hijacking the
|
|
|
|
/// process unknowingly (or deliberately).
|
|
|
|
#[inline]
|
|
|
|
pub fn call_native_fn<T: Variant + Clone>(
|
|
|
|
&self,
|
|
|
|
fn_name: impl AsRef<str>,
|
|
|
|
args: impl FuncArgs,
|
|
|
|
) -> RhaiResultOf<T> {
|
|
|
|
let mut arg_values = StaticVec::new_const();
|
|
|
|
args.parse(&mut arg_values);
|
|
|
|
|
|
|
|
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
self._call_fn_raw(fn_name, &mut args, true, false, false)
|
|
|
|
.and_then(|result| {
|
|
|
|
// Bail out early if the return type needs no cast
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2022-12-09 09:41:01 +01:00
|
|
|
return Ok(reify! { result => T });
|
2022-12-09 03:04:44 +01:00
|
|
|
}
|
2022-11-21 16:42:29 +01:00
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
let typ = self.engine().map_type_name(result.type_name());
|
2021-12-18 05:29:04 +01:00
|
|
|
|
2022-12-09 03:04:44 +01:00
|
|
|
result.try_cast().ok_or_else(|| {
|
|
|
|
let t = self.engine().map_type_name(type_name::<T>()).into();
|
|
|
|
ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into()
|
|
|
|
})
|
|
|
|
})
|
2021-12-18 05:29:04 +01:00
|
|
|
}
|
2022-10-14 10:57:14 +02:00
|
|
|
/// Call a function (native Rust or scripted) inside the call context.
|
2020-11-08 16:00:37 +01:00
|
|
|
///
|
2021-11-29 03:17:04 +01:00
|
|
|
/// If `is_method_call` is [`true`], the first argument is assumed to be the `this` pointer for
|
|
|
|
/// a script-defined function (or the object of a method call).
|
2021-10-19 17:52:58 +02:00
|
|
|
///
|
2021-11-29 06:12:47 +01:00
|
|
|
/// # WARNING - Low Level API
|
|
|
|
///
|
|
|
|
/// This function is very low level.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
2020-11-08 16:00:37 +01:00
|
|
|
///
|
2021-11-29 03:17:04 +01:00
|
|
|
/// All arguments may be _consumed_, meaning that they may be replaced by `()`. This is to avoid
|
|
|
|
/// unnecessarily cloning the arguments.
|
2020-11-20 09:52:28 +01:00
|
|
|
///
|
2021-11-29 03:17:04 +01:00
|
|
|
/// **DO NOT** reuse the arguments after this call. If they are needed afterwards, clone them
|
|
|
|
/// _before_ calling this function.
|
2020-11-08 16:00:37 +01:00
|
|
|
///
|
2021-11-29 03:17:04 +01:00
|
|
|
/// If `is_ref_mut` is [`true`], the first argument is assumed to be passed by reference and is
|
|
|
|
/// not consumed.
|
2022-10-14 10:57:14 +02:00
|
|
|
#[inline(always)]
|
2021-10-19 13:57:15 +02:00
|
|
|
pub fn call_fn_raw(
|
2020-11-30 04:20:51 +01:00
|
|
|
&self,
|
2021-11-27 16:04:45 +01:00
|
|
|
fn_name: impl AsRef<str>,
|
2021-10-19 13:57:15 +02:00
|
|
|
is_ref_mut: bool,
|
2021-06-17 03:50:32 +02:00
|
|
|
is_method_call: bool,
|
2020-11-08 16:00:37 +01:00
|
|
|
args: &mut [&mut Dynamic],
|
2021-12-25 16:49:14 +01:00
|
|
|
) -> RhaiResult {
|
2022-11-03 05:00:56 +01:00
|
|
|
let name = fn_name.as_ref();
|
2022-11-04 14:42:57 +01:00
|
|
|
let native_only = !is_valid_function_name(name);
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
let native_only = native_only && !crate::parser::is_anonymous_fn(name);
|
2022-11-03 05:00:56 +01:00
|
|
|
|
2022-11-19 11:41:51 +01:00
|
|
|
self._call_fn_raw(fn_name, args, native_only, is_ref_mut, is_method_call)
|
2022-10-14 10:57:14 +02:00
|
|
|
}
|
|
|
|
/// Call a registered native Rust function inside the call context.
|
|
|
|
///
|
|
|
|
/// This is often useful because Rust functions typically only want to cross-call other
|
|
|
|
/// registered Rust functions and not have to worry about scripted functions hijacking the
|
|
|
|
/// process unknowingly (or deliberately).
|
|
|
|
///
|
|
|
|
/// # WARNING - Low Level API
|
|
|
|
///
|
|
|
|
/// This function is very low level.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// All arguments may be _consumed_, meaning that they may be replaced by `()`. This is to avoid
|
|
|
|
/// unnecessarily cloning the arguments.
|
|
|
|
///
|
|
|
|
/// **DO NOT** reuse the arguments after this call. If they are needed afterwards, clone them
|
|
|
|
/// _before_ calling this function.
|
|
|
|
///
|
|
|
|
/// If `is_ref_mut` is [`true`], the first argument is assumed to be passed by reference and is
|
|
|
|
/// not consumed.
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn call_native_fn_raw(
|
|
|
|
&self,
|
|
|
|
fn_name: impl AsRef<str>,
|
|
|
|
is_ref_mut: bool,
|
|
|
|
args: &mut [&mut Dynamic],
|
|
|
|
) -> RhaiResult {
|
2022-11-19 11:41:51 +01:00
|
|
|
self._call_fn_raw(fn_name, args, true, is_ref_mut, false)
|
2022-10-14 10:57:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Call a function (native Rust or scripted) inside the call context.
|
|
|
|
fn _call_fn_raw(
|
|
|
|
&self,
|
|
|
|
fn_name: impl AsRef<str>,
|
2022-11-19 11:41:51 +01:00
|
|
|
args: &mut [&mut Dynamic],
|
2022-10-14 10:57:14 +02:00
|
|
|
native_only: bool,
|
|
|
|
is_ref_mut: bool,
|
|
|
|
is_method_call: bool,
|
|
|
|
) -> RhaiResult {
|
2022-12-11 09:55:30 +01:00
|
|
|
let global = &mut self.global.clone();
|
|
|
|
global.level += 1;
|
|
|
|
|
2022-10-14 10:57:14 +02:00
|
|
|
let caches = &mut Caches::new();
|
2022-01-28 11:59:18 +01:00
|
|
|
|
2021-11-27 16:04:45 +01:00
|
|
|
let fn_name = fn_name.as_ref();
|
2022-12-27 15:51:38 +01:00
|
|
|
let op_token = Token::lookup_symbol_from_syntax(fn_name);
|
2022-01-28 11:59:18 +01:00
|
|
|
let args_len = args.len();
|
2021-11-27 16:04:45 +01:00
|
|
|
|
2022-10-14 10:57:14 +02:00
|
|
|
if native_only {
|
|
|
|
return self
|
|
|
|
.engine()
|
2022-10-30 11:43:18 +01:00
|
|
|
.exec_native_fn_call(
|
2022-10-14 10:57:14 +02:00
|
|
|
global,
|
|
|
|
caches,
|
|
|
|
fn_name,
|
2023-02-10 16:42:13 +01:00
|
|
|
op_token.as_ref(),
|
2022-10-14 10:57:14 +02:00
|
|
|
calc_fn_hash(None, fn_name, args_len),
|
|
|
|
args,
|
|
|
|
is_ref_mut,
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.map(|(r, ..)| r);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Native or script
|
|
|
|
|
2021-10-19 13:57:15 +02:00
|
|
|
let hash = if is_method_call {
|
2021-11-16 06:42:46 +01:00
|
|
|
FnCallHashes::from_all(
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2022-09-21 05:46:23 +02:00
|
|
|
calc_fn_hash(None, fn_name, args_len - 1),
|
|
|
|
calc_fn_hash(None, fn_name, args_len),
|
2021-10-19 13:57:15 +02:00
|
|
|
)
|
|
|
|
} else {
|
2022-09-21 05:46:23 +02:00
|
|
|
calc_fn_hash(None, fn_name, args_len).into()
|
2021-10-19 13:57:15 +02:00
|
|
|
};
|
2021-03-08 08:30:32 +01:00
|
|
|
|
2021-10-19 13:57:15 +02:00
|
|
|
self.engine()
|
|
|
|
.exec_fn_call(
|
2022-10-14 10:57:14 +02:00
|
|
|
global,
|
|
|
|
caches,
|
2022-11-04 14:47:09 +01:00
|
|
|
None,
|
2021-10-19 13:57:15 +02:00
|
|
|
fn_name,
|
2023-02-10 16:42:13 +01:00
|
|
|
op_token.as_ref(),
|
2021-10-19 13:57:15 +02:00
|
|
|
hash,
|
|
|
|
args,
|
|
|
|
is_ref_mut,
|
|
|
|
is_method_call,
|
|
|
|
Position::NONE,
|
|
|
|
)
|
2022-02-08 02:02:15 +01:00
|
|
|
.map(|(r, ..)| r)
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
|
2022-03-17 10:00:48 +01:00
|
|
|
/// Return a mutable reference to the wrapped value of a [`Shared`] resource.
|
2020-05-26 08:14:03 +02:00
|
|
|
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
|
2020-11-09 15:44:20 +01:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2020-05-25 11:01:39 +02:00
|
|
|
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
|
2021-03-04 07:08:11 +01:00
|
|
|
Shared::make_mut(value)
|
2020-05-25 11:01:39 +02:00
|
|
|
}
|
|
|
|
|
2022-03-17 10:00:48 +01:00
|
|
|
/// Return a mutable reference to the wrapped value of a [`Shared`] resource.
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn shared_get_mut<T: Clone>(value: &mut Shared<T>) -> Option<&mut T> {
|
|
|
|
Shared::get_mut(value)
|
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise.
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2020-11-09 15:44:20 +01:00
|
|
|
pub fn shared_take_or_clone<T: Clone>(value: Shared<T>) -> T {
|
|
|
|
shared_try_take(value).unwrap_or_else(|v| v.as_ref().clone())
|
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource if is unique (i.e. not shared).
|
2020-11-09 15:44:20 +01:00
|
|
|
#[inline(always)]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2020-08-08 11:04:21 +02:00
|
|
|
pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
|
2021-03-04 07:08:11 +01:00
|
|
|
Shared::try_unwrap(value)
|
2020-08-08 10:24:10 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource, assuming that it is unique (i.e. not shared).
|
2020-05-26 08:14:03 +02:00
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the resource is shared (i.e. has other outstanding references).
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2020-08-08 11:04:21 +02:00
|
|
|
pub fn shared_take<T>(value: Shared<T>) -> T {
|
2021-11-13 05:23:35 +01:00
|
|
|
shared_try_take(value).ok().expect("not shared")
|
2020-05-25 11:01:39 +02:00
|
|
|
}
|
|
|
|
|
2022-11-15 04:22:00 +01:00
|
|
|
/// _(internals)_ Lock a [`Locked`] resource for mutable access.
|
|
|
|
/// Exported under the `internals` feature only.
|
2022-03-03 06:02:57 +01:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
#[allow(dead_code)]
|
2022-07-27 10:04:24 +02:00
|
|
|
pub fn locked_read<T>(value: &Locked<T>) -> LockGuard<T> {
|
2022-03-03 06:02:57 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
return value.borrow();
|
|
|
|
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
return value.read().unwrap();
|
|
|
|
}
|
|
|
|
|
2022-11-15 04:22:00 +01:00
|
|
|
/// _(internals)_ Lock a [`Locked`] resource for mutable access.
|
|
|
|
/// Exported under the `internals` feature only.
|
2021-11-08 04:35:46 +01:00
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
2021-11-08 05:07:49 +01:00
|
|
|
#[allow(dead_code)]
|
2022-07-27 10:04:24 +02:00
|
|
|
pub fn locked_write<T>(value: &Locked<T>) -> LockGuardMut<T> {
|
2021-11-08 04:35:46 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
return value.borrow_mut();
|
|
|
|
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
return value.write().unwrap();
|
|
|
|
}
|
|
|
|
|
2022-11-11 08:01:38 +01:00
|
|
|
/// General Rust function trail object.
|
2020-05-19 16:25:57 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-12-03 09:20:13 +01:00
|
|
|
pub type FnAny = dyn Fn(Option<NativeCallContext>, &mut FnCallArgs) -> RhaiResult;
|
2022-11-11 08:01:38 +01:00
|
|
|
/// General Rust function trail object.
|
2020-05-19 16:25:57 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2022-12-03 09:20:13 +01:00
|
|
|
pub type FnAny = dyn Fn(Option<NativeCallContext>, &mut FnCallArgs) -> RhaiResult + Send + Sync;
|
2020-05-19 16:25:57 +02:00
|
|
|
|
2022-11-11 08:01:38 +01:00
|
|
|
/// Built-in function trait object.
|
2022-12-03 09:20:13 +01:00
|
|
|
pub type FnBuiltin = (
|
|
|
|
fn(Option<NativeCallContext>, &mut FnCallArgs) -> RhaiResult,
|
|
|
|
bool,
|
|
|
|
);
|
2021-12-25 16:49:14 +01:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Function that gets an iterator from a type.
|
2022-01-27 16:55:32 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-08-22 07:10:32 +02:00
|
|
|
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>>;
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Function that gets an iterator from a type.
|
2022-01-27 16:55:32 +01:00
|
|
|
#[cfg(feature = "sync")]
|
2022-08-22 07:10:32 +02:00
|
|
|
pub type IteratorFn =
|
|
|
|
dyn Fn(Dynamic) -> Box<dyn Iterator<Item = RhaiResultOf<Dynamic>>> + Send + Sync;
|
2020-05-19 16:25:57 +02:00
|
|
|
|
2022-11-11 08:01:38 +01:00
|
|
|
/// Plugin function trait object.
|
2020-07-02 06:47:24 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-09-29 07:06:48 +02:00
|
|
|
pub type FnPlugin = dyn PluginFunction;
|
2022-11-11 08:01:38 +01:00
|
|
|
/// Plugin function trait object.
|
2020-09-29 07:06:48 +02:00
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
pub type FnPlugin = dyn PluginFunction + Send + Sync;
|
2020-07-02 06:47:24 +02:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for progress reporting.
|
2021-04-25 09:27:58 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-06-02 07:33:16 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnProgressCallback = dyn Fn(u64) -> Option<Dynamic>;
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for progress reporting.
|
2021-04-25 09:27:58 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-06-02 07:33:16 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnProgressCallback = dyn Fn(u64) -> Option<Dynamic> + Send + Sync;
|
2020-06-03 04:44:26 +02:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for printing.
|
2020-12-12 03:10:27 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnPrintCallback = dyn Fn(&str);
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for printing.
|
2020-12-12 03:10:27 +01:00
|
|
|
#[cfg(feature = "sync")]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnPrintCallback = dyn Fn(&str) + Send + Sync;
|
2020-12-12 04:47:18 +01:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for debugging.
|
2020-12-12 04:47:18 +01:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnDebugCallback = dyn Fn(&str, Option<&str>, Position);
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for debugging.
|
2020-12-12 04:47:18 +01:00
|
|
|
#[cfg(feature = "sync")]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnDebugCallback = dyn Fn(&str, Option<&str>, Position) + Send + Sync;
|
2020-12-12 03:10:27 +01:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for mapping tokens during parsing.
|
2021-09-24 12:00:48 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-09-24 16:44:39 +02:00
|
|
|
pub type OnParseTokenCallback = dyn Fn(Token, Position, &TokenizeState) -> Token;
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for mapping tokens during parsing.
|
2021-09-24 12:00:48 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2022-01-27 16:55:32 +01:00
|
|
|
pub type OnParseTokenCallback = dyn Fn(Token, Position, &TokenizeState) -> Token + Send + Sync;
|
2021-09-24 12:00:48 +02:00
|
|
|
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for variable access.
|
2020-10-11 15:58:11 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-05-01 18:03:45 +02:00
|
|
|
pub type OnVarCallback = dyn Fn(&str, usize, EvalContext) -> RhaiResultOf<Option<Dynamic>>;
|
2022-01-28 11:59:18 +01:00
|
|
|
/// Callback function for variable access.
|
2020-10-11 15:58:11 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-12-27 04:43:11 +01:00
|
|
|
pub type OnVarCallback =
|
2022-05-01 18:03:45 +02:00
|
|
|
dyn Fn(&str, usize, EvalContext) -> RhaiResultOf<Option<Dynamic>> + Send + Sync;
|
2022-02-04 15:59:41 +01:00
|
|
|
|
|
|
|
/// Callback function for variable definition.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
2022-05-01 18:03:45 +02:00
|
|
|
pub type OnDefVarCallback = dyn Fn(bool, VarDefInfo, EvalContext) -> RhaiResultOf<bool>;
|
2022-02-04 15:59:41 +01:00
|
|
|
/// Callback function for variable definition.
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
pub type OnDefVarCallback =
|
2022-05-01 18:03:45 +02:00
|
|
|
dyn Fn(bool, VarDefInfo, EvalContext) -> RhaiResultOf<bool> + Send + Sync;
|