diff --git a/src/bin/rhai-repl.rs b/src/bin/rhai-repl.rs
index fedd1dc0..8a03d85b 100644
--- a/src/bin/rhai-repl.rs
+++ b/src/bin/rhai-repl.rs
@@ -218,7 +218,7 @@ fn main() {
// println!(
// "{}",
// engine
- // .gen_fn_metadata_to_json(Some(&main_ast), false)
+ // .gen_fn_metadata_with_ast_to_json(&main_ast, true)
// .unwrap()
// );
// continue;
diff --git a/src/engine_api.rs b/src/engine_api.rs
index eb6b97f5..3ccf26bc 100644
--- a/src/engine_api.rs
+++ b/src/engine_api.rs
@@ -14,7 +14,7 @@ use crate::stdlib::{
};
use crate::{
scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, Module, NativeCallContext,
- ParseError, Position, RhaiResult, Shared, AST,
+ ParseError, Position, RhaiResult, Shared, StaticVec, AST,
};
#[cfg(not(feature = "no_index"))]
@@ -51,16 +51,28 @@ impl Engine {
/// # Ok(())
/// # }
/// ```
+ #[inline]
pub fn register_fn(&mut self, name: &str, func: F) -> &mut Self
where
F: RegisterNativeFunction,
{
+ let param_types = F::param_types();
+ let mut param_type_names: StaticVec<_> = F::param_names()
+ .iter()
+ .map(|ty| format!("_: {}", self.map_type_name(ty)))
+ .collect();
+ if F::return_type() != TypeId::of::<()>() {
+ param_type_names.push(self.map_type_name(F::return_type_name()).to_string());
+ }
+ let param_type_names: StaticVec<_> =
+ param_type_names.iter().map(|ty| ty.as_str()).collect();
+
self.global_namespace.set_fn(
name,
FnNamespace::Global,
FnAccess::Public,
- None,
- &F::param_types(),
+ Some(¶m_type_names),
+ ¶m_types,
func.into_callable_function(),
);
self
@@ -89,16 +101,26 @@ impl Engine {
/// engine.eval::("div(42, 0)")
/// .expect_err("expecting division by zero error!");
/// ```
+ #[inline]
pub fn register_result_fn(&mut self, name: &str, func: F) -> &mut Self
where
F: RegisterNativeFunction,
{
+ let param_types = F::param_types();
+ let mut param_type_names: StaticVec<_> = F::param_names()
+ .iter()
+ .map(|ty| format!("_: {}", self.map_type_name(ty)))
+ .collect();
+ param_type_names.push(self.map_type_name(F::return_type_name()).to_string());
+ let param_type_names: StaticVec<&str> =
+ param_type_names.iter().map(|ty| ty.as_str()).collect();
+
self.global_namespace.set_fn(
name,
FnNamespace::Global,
FnAccess::Public,
- None,
- &F::param_types(),
+ Some(¶m_type_names),
+ ¶m_types,
func.into_callable_function(),
);
self
diff --git a/src/fn_register.rs b/src/fn_register.rs
index f53157a0..8a773424 100644
--- a/src/fn_register.rs
+++ b/src/fn_register.rs
@@ -5,7 +5,13 @@
use crate::dynamic::{DynamicWriteLock, Variant};
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
use crate::r#unsafe::unsafe_try_cast;
-use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String, vec};
+use crate::stdlib::{
+ any::{type_name, TypeId},
+ boxed::Box,
+ mem,
+ string::String,
+ vec,
+};
use crate::{Dynamic, EvalAltResult, NativeCallContext};
// These types are used to build a unique _marker_ tuple type for each combination
@@ -55,8 +61,14 @@ pub fn by_value(data: &mut Dynamic) -> T {
/// Trait to register custom Rust functions.
pub trait RegisterNativeFunction {
- /// Get the types of this function's parameters.
+ /// Get the type ID's of this function's parameters.
fn param_types() -> Box<[TypeId]>;
+ /// Get the type names of this function's parameters.
+ fn param_names() -> Box<[&'static str]>;
+ /// Get the type ID of this function's return value.
+ fn return_type() -> TypeId;
+ /// Get the type name of this function's return value.
+ fn return_type_name() -> &'static str;
/// Convert this function into a [`CallableFunction`].
fn into_callable_function(self) -> CallableFunction;
}
@@ -78,8 +90,10 @@ macro_rules! def_register {
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), ()> for FN {
- #[inline(always)]
- fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(type_name::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn return_type() -> TypeId { TypeId::of::() }
+ #[inline(always)] fn return_type_name() -> &'static str { type_name::() }
#[inline(always)]
fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
@@ -101,8 +115,10 @@ macro_rules! def_register {
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN {
- #[inline(always)]
- fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(type_name::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn return_type() -> TypeId { TypeId::of::() }
+ #[inline(always)] fn return_type_name() -> &'static str { type_name::() }
#[inline(always)]
fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
@@ -124,8 +140,10 @@ macro_rules! def_register {
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), Result>> for FN {
- #[inline(always)]
- fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(type_name::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn return_type() -> TypeId { TypeId::of::>>() }
+ #[inline(always)] fn return_type_name() -> &'static str { type_name::>>() }
#[inline(always)]
fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
@@ -144,8 +162,10 @@ macro_rules! def_register {
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), Result>> for FN {
- #[inline(always)]
- fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(type_name::<$par>()),*].into_boxed_slice() }
+ #[inline(always)] fn return_type() -> TypeId { TypeId::of::>>() }
+ #[inline(always)] fn return_type_name() -> &'static str { type_name::>>() }
#[inline(always)]
fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {