Move all functions metadata into metadata feature.

This commit is contained in:
Stephen Chung 2021-03-24 19:27:38 +08:00
parent c4fe1782df
commit ac7f35cacb
11 changed files with 110 additions and 75 deletions

View File

@ -18,7 +18,7 @@ jobs:
os: [ubuntu-latest] os: [ubuntu-latest]
flags: flags:
- "" - ""
- "--features metadata,internals" - "--features metadata,serde,internals"
- "--features unchecked" - "--features unchecked"
- "--features sync" - "--features sync"
- "--features no_optimize" - "--features no_optimize"
@ -34,7 +34,7 @@ jobs:
- "--features no_module" - "--features no_module"
- "--features no_closure" - "--features no_closure"
- "--features unicode-xid-ident" - "--features unicode-xid-ident"
- "--features sync,no_function,no_float,no_optimize,no_module,no_closure,metadata,unchecked" - "--features sync,no_function,no_float,no_optimize,no_module,no_closure,metadata,serde,unchecked"
toolchain: [stable] toolchain: [stable]
experimental: [false] experimental: [false]
include: include:

View File

@ -27,6 +27,7 @@ Breaking changes
* `Array::reduce` and `Array::reduce_rev` now take a `Dynamic` as initial value instead of a function pointer. * `Array::reduce` and `Array::reduce_rev` now take a `Dynamic` as initial value instead of a function pointer.
* `protected`, `super` are now reserved keywords. * `protected`, `super` are now reserved keywords.
* The `Module::set_fn_XXX` API now take `&str` as the function name instead of `Into<String>`. * The `Module::set_fn_XXX` API now take `&str` as the function name instead of `Into<String>`.
* The _reflections_ API such as `Engine::gen_fn_signatures`, `Module::update_fn_metadata` etc. are put under the `metadata` feature gate.
Enhancements Enhancements
------------ ------------

View File

@ -38,7 +38,7 @@ no_closure = [] # no automatic sharing and capture of anonymous
no_module = [] # no modules no_module = [] # no modules
internals = [] # expose internal data structures internals = [] # expose internal data structures
unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers. unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers.
metadata = ["serde", "serde_json"] # enables exporting functions metadata to JSON metadata = ["serde_json"] # enable exporting functions metadata
no_std = ["smallvec/union", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"] no_std = ["smallvec/union", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"]
@ -92,4 +92,4 @@ instant = { version = "0.1" } # WASM implementation of std::time::Instant
instant = { version = "0.1" } # WASM implementation of std::time::Instant instant = { version = "0.1" } # WASM implementation of std::time::Instant
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["metadata", "internals", "decimal"] # compiling for no-std features = ["metadata", "serde", "internals", "decimal"] # compiling for no-std

View File

@ -84,6 +84,7 @@ impl fmt::Display for ScriptFnDef {
} }
/// A type containing the metadata of a script-defined function. /// A type containing the metadata of a script-defined function.
/// Not available under `no_function`.
/// ///
/// Created by [`AST::iter_functions`]. /// Created by [`AST::iter_functions`].
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
@ -260,6 +261,7 @@ impl AST {
} }
/// _(INTERNALS)_ Get the internal shared [`Module`] containing all script-defined functions. /// _(INTERNALS)_ Get the internal shared [`Module`] containing all script-defined functions.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
/// Not available under `no_function`.
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
#[deprecated = "this method is volatile and may change"] #[deprecated = "this method is volatile and may change"]
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -276,6 +278,7 @@ impl AST {
} }
/// _(INTERNALS)_ Get the internal [`Module`] containing all script-defined functions. /// _(INTERNALS)_ Get the internal [`Module`] containing all script-defined functions.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
/// Not available under `no_function`.
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
#[deprecated = "this method is volatile and may change"] #[deprecated = "this method is volatile and may change"]
#[inline(always)] #[inline(always)]
@ -311,10 +314,9 @@ impl AST {
} }
/// Clone the [`AST`]'s functions into a new [`AST`]. /// Clone the [`AST`]'s functions into a new [`AST`].
/// No statements are cloned. /// No statements are cloned.
/// Not available under `no_function`.
/// ///
/// This operation is cheap because functions are shared. /// This operation is cheap because functions are shared.
///
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn clone_functions_only(&self) -> Self { pub fn clone_functions_only(&self) -> Self {
@ -322,10 +324,9 @@ impl AST {
} }
/// Clone the [`AST`]'s functions into a new [`AST`] based on a filter predicate. /// Clone the [`AST`]'s functions into a new [`AST`] based on a filter predicate.
/// No statements are cloned. /// No statements are cloned.
/// Not available under `no_function`.
/// ///
/// This operation is cheap because functions are shared. /// This operation is cheap because functions are shared.
///
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn clone_functions_only_filtered( pub fn clone_functions_only_filtered(
@ -354,8 +355,8 @@ impl AST {
resolver: self.resolver.clone(), resolver: self.resolver.clone(),
} }
} }
/// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged, version /// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged,
/// is returned. /// version is returned.
/// ///
/// Statements in the second [`AST`] are simply appended to the end of the first _without any processing_. /// Statements in the second [`AST`] are simply appended to the end of the first _without any processing_.
/// Thus, the return value of the first [`AST`] (if using expression-statement syntax) is buried. /// Thus, the return value of the first [`AST`] (if using expression-statement syntax) is buried.

View File

@ -45,6 +45,7 @@ fn print_help() {
println!("help => print this help"); println!("help => print this help");
println!("quit, exit => quit"); println!("quit, exit => quit");
println!("scope => print all variables in the scope"); println!("scope => print all variables in the scope");
#[cfg(feature = "metadata")]
println!("functions => print all functions defined"); println!("functions => print all functions defined");
println!("ast => print the last AST (optimized)"); println!("ast => print the last AST (optimized)");
println!("astu => print the last raw, un-optimized AST"); println!("astu => print the last raw, un-optimized AST");
@ -202,6 +203,7 @@ fn main() {
println!("{:#?}\n", ast); println!("{:#?}\n", ast);
continue; continue;
} }
#[cfg(feature = "metadata")]
"functions" => { "functions" => {
// print a list of all registered functions // print a list of all registered functions
engine engine

View File

@ -9,12 +9,11 @@ use crate::stdlib::{
any::{type_name, TypeId}, any::{type_name, TypeId},
boxed::Box, boxed::Box,
format, format,
string::{String, ToString}, string::String,
vec::Vec,
}; };
use crate::{ use crate::{
scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module, scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module,
NativeCallContext, ParseError, Position, RhaiResult, Shared, StaticVec, AST, NativeCallContext, ParseError, Position, RhaiResult, Shared, AST,
}; };
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -52,30 +51,36 @@ impl Engine {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
pub fn register_fn<A, F>( pub fn register_fn<N, A, F>(&mut self, name: N, func: F) -> &mut Self
&mut self,
name: impl AsRef<str> + Into<ImmutableString>,
func: F,
) -> &mut Self
where where
N: AsRef<str> + Into<ImmutableString>,
F: RegisterNativeFunction<A, ()>, F: RegisterNativeFunction<A, ()>,
{ {
let param_types = F::param_types(); let param_types = F::param_types();
let mut param_type_names: StaticVec<_> = F::param_names()
#[cfg(feature = "metadata")]
let mut param_type_names: crate::StaticVec<_> = F::param_names()
.iter() .iter()
.map(|ty| format!("_: {}", self.map_type_name(ty))) .map(|ty| format!("_: {}", self.map_type_name(ty)))
.collect(); .collect();
#[cfg(feature = "metadata")]
if F::return_type() != TypeId::of::<()>() { if F::return_type() != TypeId::of::<()>() {
param_type_names.push(self.map_type_name(F::return_type_name()).to_string()); param_type_names.push(self.map_type_name(F::return_type_name()).into());
} }
let param_type_names: StaticVec<_> =
param_type_names.iter().map(|ty| ty.as_str()).collect(); #[cfg(feature = "metadata")]
let param_type_names: Option<crate::StaticVec<_>> =
Some(param_type_names.iter().map(|ty| ty.as_str()).collect());
#[cfg(not(feature = "metadata"))]
let param_type_names: Option<[&str; 0]> = None;
self.global_namespace.set_fn( self.global_namespace.set_fn(
name, name,
FnNamespace::Global, FnNamespace::Global,
FnAccess::Public, FnAccess::Public,
Some(&param_type_names), param_type_names.as_ref().map(|v| v.as_ref()),
&param_types, &param_types,
func.into_callable_function(), func.into_callable_function(),
); );
@ -106,28 +111,34 @@ impl Engine {
/// .expect_err("expecting division by zero error!"); /// .expect_err("expecting division by zero error!");
/// ``` /// ```
#[inline] #[inline]
pub fn register_result_fn<A, F, R>( pub fn register_result_fn<N, A, F, R>(&mut self, name: N, func: F) -> &mut Self
&mut self,
name: impl AsRef<str> + Into<ImmutableString>,
func: F,
) -> &mut Self
where where
N: AsRef<str> + Into<ImmutableString>,
F: RegisterNativeFunction<A, Result<R, Box<EvalAltResult>>>, F: RegisterNativeFunction<A, Result<R, Box<EvalAltResult>>>,
{ {
let param_types = F::param_types(); let param_types = F::param_types();
let mut param_type_names: StaticVec<_> = F::param_names()
#[cfg(feature = "metadata")]
let param_type_names: crate::StaticVec<_> = F::param_names()
.iter() .iter()
.map(|ty| format!("_: {}", self.map_type_name(ty))) .map(|ty| format!("_: {}", self.map_type_name(ty)))
.chain(crate::stdlib::iter::once(
self.map_type_name(F::return_type_name()).into(),
))
.collect(); .collect();
param_type_names.push(self.map_type_name(F::return_type_name()).to_string());
let param_type_names: StaticVec<&str> = #[cfg(feature = "metadata")]
param_type_names.iter().map(|ty| ty.as_str()).collect(); let param_type_names: Option<crate::StaticVec<_>> =
Some(param_type_names.iter().map(|ty| ty.as_str()).collect());
#[cfg(not(feature = "metadata"))]
let param_type_names: Option<[&str; 0]> = None;
self.global_namespace.set_fn( self.global_namespace.set_fn(
name, name,
FnNamespace::Global, FnNamespace::Global,
FnAccess::Public, FnAccess::Public,
Some(&param_type_names), param_type_names.as_ref().map(|v| v.as_ref()),
&param_types, &param_types,
func.into_callable_function(), func.into_callable_function(),
); );
@ -150,14 +161,18 @@ impl Engine {
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()` /// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
#[deprecated = "this function is volatile and may change"] #[deprecated = "this function is volatile and may change"]
#[inline(always)] #[inline(always)]
pub fn register_raw_fn<T: Variant + Clone>( pub fn register_raw_fn<N, T>(
&mut self, &mut self,
name: impl AsRef<str> + Into<ImmutableString>, name: N,
arg_types: &[TypeId], arg_types: &[TypeId],
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> Result<T, Box<EvalAltResult>> func: impl Fn(NativeCallContext, &mut FnCallArgs) -> Result<T, Box<EvalAltResult>>
+ SendSync + SendSync
+ 'static, + 'static,
) -> &mut Self { ) -> &mut Self
where
N: AsRef<str> + Into<ImmutableString>,
T: Variant + Clone,
{
self.global_namespace.set_raw_fn( self.global_namespace.set_raw_fn(
name, name,
FnNamespace::Global, FnNamespace::Global,
@ -1958,13 +1973,15 @@ impl Engine {
crate::optimize::optimize_into_ast(self, scope, stmt.into_vec(), lib, optimization_level) crate::optimize::optimize_into_ast(self, scope, stmt.into_vec(), lib, optimization_level)
} }
/// Generate a list of all registered functions. /// Generate a list of all registered functions.
/// Available under the `metadata` feature only.
/// ///
/// Functions from the following sources are included, in order: /// Functions from the following sources are included, in order:
/// 1) Functions registered into the global namespace /// 1) Functions registered into the global namespace
/// 2) Functions in registered sub-modules /// 2) Functions in registered sub-modules
/// 3) Functions in packages (optional) /// 3) Functions in packages (optional)
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> { #[cfg(feature = "metadata")]
let mut signatures: Vec<_> = Default::default(); pub fn gen_fn_signatures(&self, include_packages: bool) -> crate::stdlib::vec::Vec<String> {
let mut signatures: crate::stdlib::vec::Vec<_> = Default::default();
signatures.extend(self.global_namespace.gen_fn_signatures()); signatures.extend(self.global_namespace.gen_fn_signatures());

View File

@ -5,13 +5,7 @@
use crate::dynamic::{DynamicWriteLock, Variant}; use crate::dynamic::{DynamicWriteLock, Variant};
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync}; use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
use crate::r#unsafe::unsafe_try_cast; use crate::r#unsafe::unsafe_try_cast;
use crate::stdlib::{ use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String, vec};
any::{type_name, TypeId},
boxed::Box,
mem,
string::String,
vec,
};
use crate::{Dynamic, EvalAltResult, NativeCallContext}; use crate::{Dynamic, EvalAltResult, NativeCallContext};
// These types are used to build a unique _marker_ tuple type for each combination // These types are used to build a unique _marker_ tuple type for each combination
@ -66,10 +60,16 @@ pub trait RegisterNativeFunction<Args, Result> {
/// Get the type ID's of this function's parameters. /// Get the type ID's of this function's parameters.
fn param_types() -> Box<[TypeId]>; fn param_types() -> Box<[TypeId]>;
/// Get the type names of this function's parameters. /// Get the type names of this function's parameters.
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
fn param_names() -> Box<[&'static str]>; fn param_names() -> Box<[&'static str]>;
/// Get the type ID of this function's return value. /// Get the type ID of this function's return value.
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
fn return_type() -> TypeId; fn return_type() -> TypeId;
/// Get the type name of this function's return value. /// Get the type name of this function's return value.
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
fn return_type_name() -> &'static str; fn return_type_name() -> &'static str;
} }
@ -91,9 +91,9 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), ()> for FN { > 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() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(crate::stdlib::any::type_name::<$par>()),*].into_boxed_slice() }
#[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
#[inline(always)] fn return_type_name() -> &'static str { type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { crate::stdlib::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
@ -115,9 +115,9 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN { > 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() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(crate::stdlib::any::type_name::<$par>()),*].into_boxed_slice() }
#[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
#[inline(always)] fn return_type_name() -> &'static str { type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { crate::stdlib::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
@ -139,9 +139,9 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), Result<RET, Box<EvalAltResult>>> for FN { > RegisterNativeFunction<($($mark,)*), Result<RET, Box<EvalAltResult>>> 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() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(crate::stdlib::any::type_name::<$par>()),*].into_boxed_slice() }
#[inline(always)] fn return_type() -> TypeId { TypeId::of::<Result<RET, Box<EvalAltResult>>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<Result<RET, Box<EvalAltResult>>>() }
#[inline(always)] fn return_type_name() -> &'static str { type_name::<Result<RET, Box<EvalAltResult>>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { crate::stdlib::any::type_name::<Result<RET, Box<EvalAltResult>>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
@ -160,9 +160,9 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), Result<RET, Box<EvalAltResult>>> for FN { > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), Result<RET, Box<EvalAltResult>>> 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() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(crate::stdlib::any::type_name::<$par>()),*].into_boxed_slice() }
#[inline(always)] fn return_type() -> TypeId { TypeId::of::<Result<RET, Box<EvalAltResult>>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<Result<RET, Box<EvalAltResult>>>() }
#[inline(always)] fn return_type_name() -> &'static str { type_name::<Result<RET, Box<EvalAltResult>>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { crate::stdlib::any::type_name::<Result<RET, Box<EvalAltResult>>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!

View File

@ -12,7 +12,7 @@ use crate::stdlib::{
iter::empty, iter::empty,
num::NonZeroUsize, num::NonZeroUsize,
ops::{Add, AddAssign, Deref, DerefMut}, ops::{Add, AddAssign, Deref, DerefMut},
string::{String, ToString}, string::String,
vec::Vec, vec::Vec,
}; };
use crate::token::Token; use crate::token::Token;
@ -61,21 +61,21 @@ pub struct FuncInfo {
/// Parameter types (if applicable). /// Parameter types (if applicable).
pub param_types: StaticVec<TypeId>, pub param_types: StaticVec<TypeId>,
/// Parameter names (if available). /// Parameter names (if available).
#[cfg(feature = "metadata")]
pub param_names: StaticVec<ImmutableString>, pub param_names: StaticVec<ImmutableString>,
} }
impl FuncInfo { impl FuncInfo {
/// Generate a signature of the function. /// Generate a signature of the function.
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
pub fn gen_signature(&self) -> String { pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.name); let mut sig = format!("{}(", self.name);
if !self.param_names.is_empty() { if !self.param_names.is_empty() {
let mut params: Vec<_> = self let mut params: crate::stdlib::vec::Vec<String> =
.param_names self.param_names.iter().map(|s| s.as_str().into()).collect();
.iter() let return_type = params.pop().unwrap_or_else(|| "()".into());
.map(ImmutableString::to_string)
.collect();
let return_type = params.pop().unwrap_or_else(|| "()".to_string());
sig.push_str(&params.join(", ")); sig.push_str(&params.join(", "));
if return_type != "()" { if return_type != "()" {
sig.push_str(") -> "); sig.push_str(") -> ");
@ -190,7 +190,7 @@ impl fmt::Debug for Module {
.join(", ") .join(", ")
) )
} else { } else {
"".to_string() Default::default()
}, },
if !self.variables.is_empty() { if !self.variables.is_empty() {
format!( format!(
@ -202,19 +202,19 @@ impl fmt::Debug for Module {
.join(", ") .join(", ")
) )
} else { } else {
"".to_string() Default::default()
}, },
if !self.functions.is_empty() { if !self.functions.is_empty() {
format!( format!(
" functions: {}\n", " functions: {}\n",
self.functions self.functions
.values() .values()
.map(|f| f.func.to_string()) .map(|f| crate::stdlib::string::ToString::to_string(&f.func))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
) )
} else { } else {
"".to_string() Default::default()
} }
) )
} }
@ -363,6 +363,8 @@ impl Module {
} }
/// Generate signatures for all the non-private functions in the [`Module`]. /// Generate signatures for all the non-private functions in the [`Module`].
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
#[inline(always)] #[inline(always)]
pub fn gen_fn_signatures(&self) -> impl Iterator<Item = String> + '_ { pub fn gen_fn_signatures(&self) -> impl Iterator<Item = String> + '_ {
self.functions self.functions
@ -479,6 +481,7 @@ impl Module {
access: fn_def.access, access: fn_def.access,
params: num_params, params: num_params,
param_types: Default::default(), param_types: Default::default(),
#[cfg(feature = "metadata")]
param_names, param_names,
func: fn_def.into(), func: fn_def.into(),
}), }),
@ -602,6 +605,7 @@ impl Module {
} }
/// Update the metadata (parameter names/types and return type) of a registered function. /// Update the metadata (parameter names/types and return type) of a registered function.
/// Available under the `metadata` feature only.
/// ///
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call. /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
/// ///
@ -613,6 +617,7 @@ impl Module {
/// ///
/// The _last entry_ in the list should be the _return type_ of the function. /// 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. /// In other words, the number of entries should be one larger than the number of parameters.
#[cfg(feature = "metadata")]
#[inline(always)] #[inline(always)]
pub fn update_fn_metadata(&mut self, hash_fn: u64, arg_names: &[&str]) -> &mut Self { pub fn update_fn_metadata(&mut self, hash_fn: u64, arg_names: &[&str]) -> &mut Self {
let param_names = arg_names let param_names = arg_names
@ -652,7 +657,7 @@ impl Module {
name: impl AsRef<str> + Into<ImmutableString>, name: impl AsRef<str> + Into<ImmutableString>,
namespace: FnNamespace, namespace: FnNamespace,
access: FnAccess, access: FnAccess,
arg_names: Option<&[&str]>, _arg_names: Option<&[&str]>,
arg_types: &[TypeId], arg_types: &[TypeId],
func: CallableFunction, func: CallableFunction,
) -> u64 { ) -> u64 {
@ -683,7 +688,9 @@ impl Module {
let hash_fn = calc_native_fn_hash(empty(), &name, &param_types); let hash_fn = calc_native_fn_hash(empty(), &name, &param_types);
let name = self.interned_strings.get(name); let name = self.interned_strings.get(name);
let param_names = arg_names
#[cfg(feature = "metadata")]
let param_names = _arg_names
.iter() .iter()
.flat_map(|p| p.iter()) .flat_map(|p| p.iter())
.map(|&arg| self.interned_strings.get(arg)) .map(|&arg| self.interned_strings.get(arg))
@ -697,6 +704,7 @@ impl Module {
access, access,
params: param_types.len(), params: param_types.len(),
param_types, param_types,
#[cfg(feature = "metadata")]
param_names, param_names,
func: func.into(), func: func.into(),
}), }),

View File

@ -142,8 +142,10 @@ macro_rules! reg_range {
($lib:ident | $x:expr => $( $y:ty ),*) => { ($lib:ident | $x:expr => $( $y:ty ),*) => {
$( $(
$lib.set_iterator::<Range<$y>>(); $lib.set_iterator::<Range<$y>>();
let hash = $lib.set_native_fn($x, get_range::<$y>); let _hash = $lib.set_native_fn($x, get_range::<$y>);
$lib.update_fn_metadata(hash, &[
#[cfg(feature = "metadata")]
$lib.update_fn_metadata(_hash, &[
concat!("from: ", stringify!($y)), concat!("from: ", stringify!($y)),
concat!("to: ", stringify!($y)), concat!("to: ", stringify!($y)),
concat!("Iterator<Item=", stringify!($y), ">") concat!("Iterator<Item=", stringify!($y), ">")
@ -153,8 +155,10 @@ macro_rules! reg_range {
($lib:ident | step $x:expr => $( $y:ty ),*) => { ($lib:ident | step $x:expr => $( $y:ty ),*) => {
$( $(
$lib.set_iterator::<StepRange<$y>>(); $lib.set_iterator::<StepRange<$y>>();
let hash = $lib.set_native_fn($x, get_step_range::<$y>); let _hash = $lib.set_native_fn($x, get_step_range::<$y>);
$lib.update_fn_metadata(hash, &[
#[cfg(feature = "metadata")]
$lib.update_fn_metadata(_hash, &[
concat!("from: ", stringify!($y)), concat!("from: ", stringify!($y)),
concat!("to: ", stringify!($y)), concat!("to: ", stringify!($y)),
concat!("step: ", stringify!($y)), concat!("step: ", stringify!($y)),

View File

@ -211,7 +211,8 @@ impl From<&crate::Module> for ModuleMetadata {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
impl Engine { impl Engine {
/// _(METADATA)_ Generate a list of all functions (including those defined in an /// _(METADATA)_ Generate a list of all functions (including those defined in an
/// [`AST`][crate::AST]) in JSON format. Available only under the `metadata` feature. /// [`AST`][crate::AST]) in JSON format.
/// Available under the `metadata` feature only.
/// ///
/// Functions from the following sources are included: /// Functions from the following sources are included:
/// 1) Functions defined in an [`AST`][crate::AST] /// 1) Functions defined in an [`AST`][crate::AST]

View File

@ -8,6 +8,7 @@ mod serialize;
mod str; mod str;
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
#[cfg(feature = "serde")]
mod metadata; mod metadata;
pub use de::from_dynamic; pub use de::from_dynamic;