From 27953ef74500085eeaf35f24c9b52935e9a1b41c Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 15 Mar 2021 22:19:21 +0800 Subject: [PATCH] Register parameter type names. --- src/bin/rhai-repl.rs | 2 +- src/engine_api.rs | 32 +++++++++++++++++++++++++++----- src/fn_register.rs | 40 ++++++++++++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 16 deletions(-) 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| {