rhai/src/func/func.rs

117 lines
4.6 KiB
Rust
Raw Normal View History

//! Module which defines the function registration mechanism.
#![cfg(not(feature = "no_function"))]
#![allow(non_snake_case)]
2021-12-25 16:49:14 +01:00
use crate::parser::ParseResult;
2021-11-13 15:36:23 +01:00
use crate::types::dynamic::Variant;
2021-12-25 16:49:14 +01:00
use crate::{Engine, RhaiResultOf, Scope, SmartString, AST};
2021-04-17 09:15:54 +02:00
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
2020-04-09 04:38:33 +02:00
/// Trait to create a Rust closure from a script.
///
2021-01-28 09:48:56 +01:00
/// Not available under `no_function`.
2020-04-09 04:38:33 +02:00
pub trait Func<ARGS, RET> {
2022-06-05 12:17:44 +02:00
/// The closure's output type.
type Output;
2020-11-20 09:52:28 +01:00
/// Create a Rust closure from an [`AST`].
2021-01-02 16:30:10 +01:00
///
2020-11-20 09:52:28 +01:00
/// The [`Engine`] and [`AST`] are consumed and basically embedded into the closure.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
2021-03-17 15:32:22 +01:00
/// use rhai::{Engine, Func}; // use 'Func' for 'create_from_ast'
///
2021-03-17 15:32:22 +01:00
/// let engine = Engine::new(); // create a new 'Engine' just for this
///
/// let ast = engine.compile("fn calc(x, y) { x + len(y) < 42 }")?;
///
2020-04-09 04:38:33 +02:00
/// // Func takes two type parameters:
/// // 1) a tuple made up of the types of the script function's parameters
/// // 2) the return type of the script function
2020-12-26 06:05:57 +01:00
///
/// // 'func' will have type Box<dyn Fn(i64, String) -> Result<bool, Box<EvalAltResult>>> and is callable!
2021-03-17 15:32:22 +01:00
/// let func = Func::<(i64, &str), bool>::create_from_ast(
/// // ^^^^^^^^^^^ function parameter types in tuple
///
2020-12-26 06:05:57 +01:00
/// engine, // the 'Engine' is consumed into the closure
/// ast, // the 'AST'
/// "calc" // the entry-point function name
/// );
///
2021-03-17 15:32:22 +01:00
/// func(123, "hello")? == false; // call the anonymous function
/// # Ok(())
/// # }
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output;
/// Create a Rust closure from a script.
2021-01-02 16:30:10 +01:00
///
2020-11-20 09:52:28 +01:00
/// The [`Engine`] is consumed and basically embedded into the closure.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
2021-03-17 15:32:22 +01:00
/// use rhai::{Engine, Func}; // use 'Func' for 'create_from_script'
///
2021-03-17 15:32:22 +01:00
/// let engine = Engine::new(); // create a new 'Engine' just for this
///
/// let script = "fn calc(x, y) { x + len(y) < 42 }";
///
2020-04-09 04:38:33 +02:00
/// // Func takes two type parameters:
/// // 1) a tuple made up of the types of the script function's parameters
/// // 2) the return type of the script function
2020-12-26 06:05:57 +01:00
///
/// // 'func' will have type Box<dyn Fn(i64, String) -> Result<bool, Box<EvalAltResult>>> and is callable!
2021-03-17 15:32:22 +01:00
/// let func = Func::<(i64, &str), bool>::create_from_script(
/// // ^^^^^^^^^^^ function parameter types in tuple
///
2020-12-26 06:05:57 +01:00
/// engine, // the 'Engine' is consumed into the closure
/// script, // the script, notice number of parameters must match
/// "calc" // the entry-point function name
/// )?;
///
2021-03-17 15:32:22 +01:00
/// func(123, "hello")? == false; // call the anonymous function
/// # Ok(())
/// # }
/// ```
2021-12-25 16:49:14 +01:00
fn create_from_script(self, script: &str, entry_point: &str) -> ParseResult<Self::Output>;
}
macro_rules! def_anonymous_fn {
() => {
def_anonymous_fn!(imp);
};
(imp $($par:ident),*) => {
2020-04-16 17:31:48 +02:00
impl<$($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine
{
#[cfg(feature = "sync")]
2021-12-25 16:49:14 +01:00
type Output = Box<dyn Fn($($par),*) -> RhaiResultOf<RET> + Send + Sync>;
#[cfg(not(feature = "sync"))]
2021-12-25 16:49:14 +01:00
type Output = Box<dyn Fn($($par),*) -> RhaiResultOf<RET>>;
#[inline]
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
2021-05-29 12:33:29 +02:00
let fn_name: SmartString = entry_point.into();
2021-03-22 04:18:09 +01:00
Box::new(move |$($par),*| self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*)))
}
#[inline]
2021-12-25 16:49:14 +01:00
fn create_from_script(self, script: &str, entry_point: &str) -> ParseResult<Self::Output> {
let ast = self.compile(script)?;
2020-04-09 04:38:33 +02:00
Ok(Func::<($($par,)*), RET>::create_from_ast(self, ast, entry_point))
}
}
};
($p0:ident $(, $p:ident)*) => {
def_anonymous_fn!(imp $p0 $(, $p)*);
def_anonymous_fn!($($p),*);
};
}
def_anonymous_fn!(A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V);