Add gen_fn_siguatures API.

This commit is contained in:
Stephen Chung 2020-11-22 17:21:34 +08:00
parent 739dce72e3
commit 07fe132e1a
17 changed files with 400 additions and 83 deletions

View File

@ -10,6 +10,9 @@ It also allows exposing selected module functions (usually methods) to the globa
This is very convenient when encapsulating the API of a custom Rust type into a module while having methods This is very convenient when encapsulating the API of a custom Rust type into a module while having methods
and iterators registered on the custom type work normally. and iterators registered on the custom type work normally.
A new `gen_fn_signatures` API enables enumerating the registered functions of an `Engine` for documentation purposes.
It also prepares the way for a future reflection API.
Bug fixes Bug fixes
--------- ---------
@ -19,6 +22,7 @@ Breaking changes
---------------- ----------------
* `Module::set_fn`, `Module::set_raw_fn` and `Module::set_fn_XXX_mut` all take an additional parameter of `FnNamespace`. * `Module::set_fn`, `Module::set_raw_fn` and `Module::set_fn_XXX_mut` all take an additional parameter of `FnNamespace`.
* `Module::set_fn` takes a further parameter with a list of parameter names and types, if any.
* `Module::get_sub_module_mut` is removed. * `Module::get_sub_module_mut` is removed.
* `begin`, `end`, `unless` are now reserved keywords. * `begin`, `end`, `unless` are now reserved keywords.
* `EvalPackage` is removed in favor of `Engine::disable_symbol`. * `EvalPackage` is removed in favor of `Engine::disable_symbol`.
@ -26,13 +30,15 @@ Breaking changes
New features New features
------------ ------------
* `switch` statement. * New `switch` statement.
* `do ... while` and `do ... until` statement. * New `do ... while` and `do ... until` statements.
* `Engine::register_module` to register a module as a sub-module in the global namespace. * New `Engine::gen_fn_signatures`, `Module::gen_fn_signatures` and `PackagesCollection::gen_fn_signatures` to generate a list of signatures for functions registered.
* `set_exported_global_fn!` macro to register a plugin function and expose it to the global namespace. * New `Engine::register_module` to register a module as a sub-module in the global namespace.
* New `set_exported_global_fn!` macro to register a plugin function and expose it to the global namespace.
* `Module::set_fn_XXX_mut` can expose a module function to the global namespace. This is convenient when registering an API for a custom type. * `Module::set_fn_XXX_mut` can expose a module function to the global namespace. This is convenient when registering an API for a custom type.
* `Module::set_getter_fn`, `Module::set_setter_fn`, `Module::set_indexer_get_fn`, `Module::set_indexer_set_fn` all expose the function to the global namespace by default. This is convenient when registering an API for a custom type. * `Module::set_getter_fn`, `Module::set_setter_fn`, `Module::set_indexer_get_fn`, `Module::set_indexer_set_fn` all expose the function to the global namespace by default. This is convenient when registering an API for a custom type.
* `#[rhai_fn(global)]` and `#[rhai_fn(internal)]` attributes to determine whether a function defined in a plugin module should be exposed to the global namespace. This is convenient when defining an API for a custom type. * New `Module::update_fn_param_names` to update a module function's parameter names and types.
* New `#[rhai_fn(global)]` and `#[rhai_fn(internal)]` attributes to determine whether a function defined in a plugin module should be exposed to the global namespace. This is convenient when defining an API for a custom type.
Enhancements Enhancements
------------ ------------

View File

@ -12,7 +12,7 @@ use std::format;
use std::borrow::Cow; use std::borrow::Cow;
use quote::{quote, quote_spanned}; use quote::{quote, quote_spanned, ToTokens};
use syn::{ use syn::{
parse::{Parse, ParseStream, Parser}, parse::{Parse, ParseStream, Parser},
spanned::Spanned, spanned::Spanned,
@ -83,6 +83,10 @@ pub(crate) fn flatten_type_groups(ty: &syn::Type) -> &syn::Type {
} }
} }
pub(crate) fn print_type(ty: &syn::Type) -> String {
ty.to_token_stream().to_string().replace("& ", "&")
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct ExportedFnParams { pub(crate) struct ExportedFnParams {
pub name: Option<Vec<String>>, pub name: Option<Vec<String>>,
@ -576,6 +580,7 @@ impl ExportedFn {
syn::Ident::new(&format!("rhai_fn_{}", self.name()), self.name().span()); syn::Ident::new(&format!("rhai_fn_{}", self.name()), self.name().span());
let impl_block = self.generate_impl("Token"); let impl_block = self.generate_impl("Token");
let callable_block = self.generate_callable("Token"); let callable_block = self.generate_callable("Token");
let input_names_block = self.generate_input_names("Token");
let input_types_block = self.generate_input_types("Token"); let input_types_block = self.generate_input_types("Token");
let dyn_result_fn_block = self.generate_dynamic_fn(); let dyn_result_fn_block = self.generate_dynamic_fn();
quote! { quote! {
@ -585,6 +590,7 @@ impl ExportedFn {
struct Token(); struct Token();
#impl_block #impl_block
#callable_block #callable_block
#input_names_block
#input_types_block #input_types_block
#dyn_result_fn_block #dyn_result_fn_block
} }
@ -655,6 +661,19 @@ impl ExportedFn {
} }
} }
pub fn generate_input_names(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_names_fn_name: syn::Ident = syn::Ident::new(
format!("{}_input_names", on_type_name.to_lowercase()).as_str(),
self.name().span(),
);
quote! {
pub fn #input_names_fn_name() -> Box<[&'static str]> {
#token_name().input_names()
}
}
}
pub fn generate_input_types(&self, on_type_name: &str) -> proc_macro2::TokenStream { pub fn generate_input_types(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span()); let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_types_fn_name: syn::Ident = syn::Ident::new( let input_types_fn_name: syn::Ident = syn::Ident::new(
@ -680,6 +699,7 @@ impl ExportedFn {
let mut unpack_stmts: Vec<syn::Stmt> = Vec::new(); let mut unpack_stmts: Vec<syn::Stmt> = Vec::new();
let mut unpack_exprs: Vec<syn::Expr> = Vec::new(); let mut unpack_exprs: Vec<syn::Expr> = Vec::new();
let mut input_type_names: Vec<String> = Vec::new();
let mut input_type_exprs: Vec<syn::Expr> = Vec::new(); let mut input_type_exprs: Vec<syn::Expr> = Vec::new();
let skip_first_arg; let skip_first_arg;
@ -693,8 +713,9 @@ impl ExportedFn {
let first_arg = self.arg_list().next().unwrap(); let first_arg = self.arg_list().next().unwrap();
let var = syn::Ident::new("arg0", proc_macro2::Span::call_site()); let var = syn::Ident::new("arg0", proc_macro2::Span::call_site());
match first_arg { match first_arg {
syn::FnArg::Typed(pattern) => { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
let arg_type = match flatten_type_groups(pattern.ty.as_ref()) { let arg_name = format!("{}: {}", pat.to_token_stream(), print_type(ty));
let arg_type = match flatten_type_groups(ty.as_ref()) {
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(), syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
p => p, p => p,
}; };
@ -706,6 +727,7 @@ impl ExportedFn {
}) })
.unwrap(), .unwrap(),
); );
input_type_names.push(arg_name);
input_type_exprs.push( input_type_exprs.push(
syn::parse2::<syn::Expr>(quote_spanned!( syn::parse2::<syn::Expr>(quote_spanned!(
arg_type.span()=> TypeId::of::<#arg_type>() arg_type.span()=> TypeId::of::<#arg_type>()
@ -731,9 +753,10 @@ impl ExportedFn {
let is_string; let is_string;
let is_ref; let is_ref;
match arg { match arg {
syn::FnArg::Typed(pattern) => { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
let arg_type = pattern.ty.as_ref(); let arg_name = format!("{}: {}", pat.to_token_stream(), print_type(ty));
let downcast_span = match flatten_type_groups(pattern.ty.as_ref()) { let arg_type = ty.as_ref();
let downcast_span = match flatten_type_groups(arg_type) {
syn::Type::Reference(syn::TypeReference { syn::Type::Reference(syn::TypeReference {
mutability: None, mutability: None,
ref elem, ref elem,
@ -767,6 +790,7 @@ impl ExportedFn {
}) })
.unwrap(), .unwrap(),
); );
input_type_names.push(arg_name);
if !is_string { if !is_string {
input_type_exprs.push( input_type_exprs.push(
syn::parse2::<syn::Expr>(quote_spanned!( syn::parse2::<syn::Expr>(quote_spanned!(
@ -837,6 +861,9 @@ impl ExportedFn {
fn is_method_call(&self) -> bool { #is_method_call } fn is_method_call(&self) -> bool { #is_method_call }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(#type_name()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(#type_name()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![#(#input_type_names),*].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![#(#input_type_exprs),*].into_boxed_slice() new_vec![#(#input_type_exprs),*].into_boxed_slice()
} }

View File

@ -340,6 +340,7 @@ pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream
let gen_mod_path = crate::register::generated_module_path(&rust_modpath); let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
let tokens = quote! { let tokens = quote! {
#module_expr.set_fn(#export_name, FnNamespace::Internal, FnAccess::Public, #module_expr.set_fn(#export_name, FnNamespace::Internal, FnAccess::Public,
Some(#gen_mod_path::token_input_names().as_ref()),
#gen_mod_path::token_input_types().as_ref(), #gen_mod_path::token_input_types().as_ref(),
#gen_mod_path::token_callable()); #gen_mod_path::token_callable());
}; };
@ -381,6 +382,7 @@ pub fn set_exported_global_fn(args: proc_macro::TokenStream) -> proc_macro::Toke
let gen_mod_path = crate::register::generated_module_path(&rust_modpath); let gen_mod_path = crate::register::generated_module_path(&rust_modpath);
let tokens = quote! { let tokens = quote! {
#module_expr.set_fn(#export_name, FnNamespace::Global, FnAccess::Public, #module_expr.set_fn(#export_name, FnNamespace::Global, FnAccess::Public,
Some(#gen_mod_path::token_input_names().as_ref()),
#gen_mod_path::token_input_types().as_ref(), #gen_mod_path::token_input_types().as_ref(),
#gen_mod_path::token_callable()); #gen_mod_path::token_callable());
}; };

View File

@ -3,8 +3,9 @@ use std::collections::HashMap;
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use crate::attrs::ExportScope; use crate::attrs::ExportScope;
use crate::function::flatten_type_groups; use crate::function::{
use crate::function::{ExportedFn, FnNamespaceAccess, FnSpecialAccess}; flatten_type_groups, print_type, ExportedFn, FnNamespaceAccess, FnSpecialAccess,
};
use crate::module::Module; use crate::module::Module;
pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr); pub(crate) type ExportedConst = (String, Box<syn::Type>, syn::Expr);
@ -82,6 +83,16 @@ pub(crate) fn generate_body(
let reg_names = function.exported_names(); let reg_names = function.exported_names();
let mut namespace = FnNamespaceAccess::Internal; let mut namespace = FnNamespaceAccess::Internal;
let fn_input_names: Vec<String> = function
.arg_list()
.map(|fnarg| match fnarg {
syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"),
syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
format!("{}: {}", pat.to_token_stream(), print_type(ty))
}
})
.collect();
let fn_input_types: Vec<syn::Expr> = function let fn_input_types: Vec<syn::Expr> = function
.arg_list() .arg_list()
.map(|fnarg| match fnarg { .map(|fnarg| match fnarg {
@ -117,6 +128,7 @@ pub(crate) fn generate_body(
}, },
t => t.clone(), t => t.clone(),
}; };
syn::parse2::<syn::Expr>(quote! { syn::parse2::<syn::Expr>(quote! {
core::any::TypeId::of::<#arg_type>()}) core::any::TypeId::of::<#arg_type>()})
.unwrap() .unwrap()
@ -138,7 +150,8 @@ pub(crate) fn generate_body(
); );
set_fn_stmts.push( set_fn_stmts.push(
syn::parse2::<syn::Stmt>(quote! { syn::parse2::<syn::Stmt>(quote! {
m.set_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public, &[#(#fn_input_types),*], m.set_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public,
Some(&[#(#fn_input_names),*]), &[#(#fn_input_types),*],
#fn_token_name().into()); #fn_token_name().into());
}) })
.unwrap(), .unwrap(),
@ -151,6 +164,7 @@ pub(crate) fn generate_body(
}); });
gen_fn_tokens.push(function.generate_impl(&fn_token_name.to_string())); gen_fn_tokens.push(function.generate_impl(&fn_token_name.to_string()));
gen_fn_tokens.push(function.generate_callable(&fn_token_name.to_string())); gen_fn_tokens.push(function.generate_callable(&fn_token_name.to_string()));
gen_fn_tokens.push(function.generate_input_names(&fn_token_name.to_string()));
gen_fn_tokens.push(function.generate_input_types(&fn_token_name.to_string())); gen_fn_tokens.push(function.generate_input_types(&fn_token_name.to_string()));
} }
@ -195,9 +209,7 @@ pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::
.fold(name.to_string(), |mut argstr, fnarg| { .fold(name.to_string(), |mut argstr, fnarg| {
let type_string: String = match fnarg { let type_string: String = match fnarg {
syn::FnArg::Receiver(_) => unimplemented!("receiver rhai_fns not implemented"), syn::FnArg::Receiver(_) => unimplemented!("receiver rhai_fns not implemented"),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => { syn::FnArg::Typed(syn::PatType { ref ty, .. }) => print_type(ty),
ty.as_ref().to_token_stream().to_string()
}
}; };
argstr.push('.'); argstr.push('.');
argstr.push_str(&type_string); argstr.push_str(&type_string);

View File

@ -286,6 +286,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![].into_boxed_slice() new_vec![].into_boxed_slice()
} }
@ -293,6 +296,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -328,6 +334,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: usize"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<usize>()].into_boxed_slice() new_vec![TypeId::of::<usize>()].into_boxed_slice()
} }
@ -335,6 +344,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -370,6 +382,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: usize"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<usize>()].into_boxed_slice() new_vec![TypeId::of::<usize>()].into_boxed_slice()
} }
@ -377,6 +392,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -414,6 +432,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![].into_boxed_slice() new_vec![].into_boxed_slice()
} }
@ -421,6 +442,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -452,6 +476,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(MyType()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(MyType()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: usize"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<usize>()].into_boxed_slice() new_vec![TypeId::of::<usize>()].into_boxed_slice()
} }
@ -485,6 +512,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: usize", "y: usize"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<usize>(), new_vec![TypeId::of::<usize>(),
TypeId::of::<usize>()].into_boxed_slice() TypeId::of::<usize>()].into_boxed_slice()
@ -493,6 +523,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -529,6 +562,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { true } fn is_method_call(&self) -> bool { true }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut usize", "y: usize"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<usize>(), new_vec![TypeId::of::<usize>(),
TypeId::of::<usize>()].into_boxed_slice() TypeId::of::<usize>()].into_boxed_slice()
@ -537,6 +573,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }
@ -573,6 +612,9 @@ mod generate_tests {
fn is_method_call(&self) -> bool { false } fn is_method_call(&self) -> bool { false }
fn is_variadic(&self) -> bool { false } fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) } fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(Token()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["message: &str"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice() new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice()
} }
@ -580,6 +622,9 @@ mod generate_tests {
pub fn token_callable() -> CallableFunction { pub fn token_callable() -> CallableFunction {
Token().into() Token().into()
} }
pub fn token_input_names() -> Box<[&'static str]> {
Token().input_names()
}
pub fn token_input_types() -> Box<[TypeId]> { pub fn token_input_types() -> Box<[TypeId]> {
Token().input_types() Token().input_types()
} }

View File

@ -297,7 +297,7 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, &[], m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, Some(&[]), &[],
get_mystic_number_token().into()); get_mystic_number_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -315,6 +315,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(get_mystic_number_token()) Box::new(get_mystic_number_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![].into_boxed_slice() new_vec![].into_boxed_slice()
} }
@ -322,6 +325,9 @@ mod generate_tests {
pub fn get_mystic_number_token_callable() -> CallableFunction { pub fn get_mystic_number_token_callable() -> CallableFunction {
get_mystic_number_token().into() get_mystic_number_token().into()
} }
pub fn get_mystic_number_token_input_names() -> Box<[&'static str]> {
get_mystic_number_token().input_names()
}
pub fn get_mystic_number_token_input_types() -> Box<[TypeId]> { pub fn get_mystic_number_token_input_types() -> Box<[TypeId]> {
get_mystic_number_token().input_types() get_mystic_number_token().input_types()
} }
@ -359,7 +365,7 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("add_one_to", FnNamespace::Global, FnAccess::Public, &[core::any::TypeId::of::<INT>()], m.set_fn("add_one_to", FnNamespace::Global, FnAccess::Public, Some(&["x: INT"]), &[core::any::TypeId::of::<INT>()],
add_one_to_token().into()); add_one_to_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -378,6 +384,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_one_to_token()) Box::new(add_one_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>()].into_boxed_slice() new_vec![TypeId::of::<INT>()].into_boxed_slice()
} }
@ -385,6 +394,9 @@ mod generate_tests {
pub fn add_one_to_token_callable() -> CallableFunction { pub fn add_one_to_token_callable() -> CallableFunction {
add_one_to_token().into() add_one_to_token().into()
} }
pub fn add_one_to_token_input_names() -> Box<[&'static str]> {
add_one_to_token().input_names()
}
pub fn add_one_to_token_input_types() -> Box<[TypeId]> { pub fn add_one_to_token_input_types() -> Box<[TypeId]> {
add_one_to_token().input_types() add_one_to_token().input_types()
} }
@ -421,7 +433,7 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("add_one_to", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>()], m.set_fn("add_one_to", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT"]), &[core::any::TypeId::of::<INT>()],
add_one_to_token().into()); add_one_to_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -440,6 +452,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_one_to_token()) Box::new(add_one_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>()].into_boxed_slice() new_vec![TypeId::of::<INT>()].into_boxed_slice()
} }
@ -447,6 +462,9 @@ mod generate_tests {
pub fn add_one_to_token_callable() -> CallableFunction { pub fn add_one_to_token_callable() -> CallableFunction {
add_one_to_token().into() add_one_to_token().into()
} }
pub fn add_one_to_token_input_names() -> Box<[&'static str]> {
add_one_to_token().input_names()
}
pub fn add_one_to_token_input_types() -> Box<[TypeId]> { pub fn add_one_to_token_input_types() -> Box<[TypeId]> {
add_one_to_token().input_types() add_one_to_token().input_types()
} }
@ -494,10 +512,10 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>()], m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT"]), &[core::any::TypeId::of::<INT>()],
add_one_to_token().into()); add_one_to_token().into());
m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(), m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT", "y: INT"]),
core::any::TypeId::of::<INT>()], &[core::any::TypeId::of::<INT>(), core::any::TypeId::of::<INT>()],
add_n_to_token().into()); add_n_to_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -516,6 +534,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_one_to_token()) Box::new(add_one_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>()].into_boxed_slice() new_vec![TypeId::of::<INT>()].into_boxed_slice()
} }
@ -523,6 +544,9 @@ mod generate_tests {
pub fn add_one_to_token_callable() -> CallableFunction { pub fn add_one_to_token_callable() -> CallableFunction {
add_one_to_token().into() add_one_to_token().into()
} }
pub fn add_one_to_token_input_names() -> Box<[&'static str]> {
add_one_to_token().input_names()
}
pub fn add_one_to_token_input_types() -> Box<[TypeId]> { pub fn add_one_to_token_input_types() -> Box<[TypeId]> {
add_one_to_token().input_types() add_one_to_token().input_types()
} }
@ -543,6 +567,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_n_to_token()) Box::new(add_n_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT", "y: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>(), new_vec![TypeId::of::<INT>(),
TypeId::of::<INT>()].into_boxed_slice() TypeId::of::<INT>()].into_boxed_slice()
@ -551,6 +578,9 @@ mod generate_tests {
pub fn add_n_to_token_callable() -> CallableFunction { pub fn add_n_to_token_callable() -> CallableFunction {
add_n_to_token().into() add_n_to_token().into()
} }
pub fn add_n_to_token_input_names() -> Box<[&'static str]> {
add_n_to_token().input_names()
}
pub fn add_n_to_token_input_types() -> Box<[TypeId]> { pub fn add_n_to_token_input_types() -> Box<[TypeId]> {
add_n_to_token().input_types() add_n_to_token().input_types()
} }
@ -587,8 +617,8 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(), m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT", "y: INT"]),
core::any::TypeId::of::<INT>()], &[core::any::TypeId::of::<INT>(), core::any::TypeId::of::<INT>()],
add_together_token().into()); add_together_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -608,6 +638,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_together_token()) Box::new(add_together_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT", "y: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>(), new_vec![TypeId::of::<INT>(),
TypeId::of::<INT>()].into_boxed_slice() TypeId::of::<INT>()].into_boxed_slice()
@ -616,6 +649,9 @@ mod generate_tests {
pub fn add_together_token_callable() -> CallableFunction { pub fn add_together_token_callable() -> CallableFunction {
add_together_token().into() add_together_token().into()
} }
pub fn add_together_token_input_names() -> Box<[&'static str]> {
add_together_token().input_names()
}
pub fn add_together_token_input_types() -> Box<[TypeId]> { pub fn add_together_token_input_types() -> Box<[TypeId]> {
add_together_token().input_types() add_together_token().input_types()
} }
@ -653,14 +689,14 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("add", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(), m.set_fn("add", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT", "y: INT"]),
core::any::TypeId::of::<INT>()], &[core::any::TypeId::of::<INT>(), core::any::TypeId::of::<INT>()],
add_together_token().into()); add_together_token().into());
m.set_fn("+", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(), m.set_fn("+", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT", "y: INT"]),
core::any::TypeId::of::<INT>()], &[core::any::TypeId::of::<INT>(), core::any::TypeId::of::<INT>()],
add_together_token().into()); add_together_token().into());
m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<INT>(), m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(&["x: INT", "y: INT"]),
core::any::TypeId::of::<INT>()], &[core::any::TypeId::of::<INT>(), core::any::TypeId::of::<INT>()],
add_together_token().into()); add_together_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -680,6 +716,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(add_together_token()) Box::new(add_together_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: INT", "y: INT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<INT>(), new_vec![TypeId::of::<INT>(),
TypeId::of::<INT>()].into_boxed_slice() TypeId::of::<INT>()].into_boxed_slice()
@ -688,6 +727,9 @@ mod generate_tests {
pub fn add_together_token_callable() -> CallableFunction { pub fn add_together_token_callable() -> CallableFunction {
add_together_token().into() add_together_token().into()
} }
pub fn add_together_token_input_names() -> Box<[&'static str]> {
add_together_token().input_names()
}
pub fn add_together_token_input_types() -> Box<[TypeId]> { pub fn add_together_token_input_types() -> Box<[TypeId]> {
add_together_token().input_types() add_together_token().input_types()
} }
@ -906,7 +948,7 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, &[], m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, Some(&[]), &[],
get_mystic_number_token().into()); get_mystic_number_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -924,6 +966,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(get_mystic_number_token()) Box::new(get_mystic_number_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![].into_boxed_slice() new_vec![].into_boxed_slice()
} }
@ -931,6 +976,9 @@ mod generate_tests {
pub fn get_mystic_number_token_callable() -> CallableFunction { pub fn get_mystic_number_token_callable() -> CallableFunction {
get_mystic_number_token().into() get_mystic_number_token().into()
} }
pub fn get_mystic_number_token_input_names() -> Box<[&'static str]> {
get_mystic_number_token().input_names()
}
pub fn get_mystic_number_token_input_types() -> Box<[TypeId]> { pub fn get_mystic_number_token_input_types() -> Box<[TypeId]> {
get_mystic_number_token().input_types() get_mystic_number_token().input_types()
} }
@ -999,7 +1047,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public,
&[core::any::TypeId::of::<ImmutableString>()], Some(&["x: &str"]), &[core::any::TypeId::of::<ImmutableString>()],
print_out_to_token().into()); print_out_to_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1018,6 +1066,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(print_out_to_token()) Box::new(print_out_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &str"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice() new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice()
} }
@ -1025,6 +1076,9 @@ mod generate_tests {
pub fn print_out_to_token_callable() -> CallableFunction { pub fn print_out_to_token_callable() -> CallableFunction {
print_out_to_token().into() print_out_to_token().into()
} }
pub fn print_out_to_token_input_names() -> Box<[&'static str]> {
print_out_to_token().input_names()
}
pub fn print_out_to_token_input_types() -> Box<[TypeId]> { pub fn print_out_to_token_input_types() -> Box<[TypeId]> {
print_out_to_token().input_types() print_out_to_token().input_types()
} }
@ -1062,7 +1116,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public,
&[core::any::TypeId::of::<ImmutableString>()], Some(&["x: String"]), &[core::any::TypeId::of::<ImmutableString>()],
print_out_to_token().into()); print_out_to_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1081,6 +1135,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(print_out_to_token()) Box::new(print_out_to_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: String"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice() new_vec![TypeId::of::<ImmutableString>()].into_boxed_slice()
} }
@ -1088,6 +1145,9 @@ mod generate_tests {
pub fn print_out_to_token_callable() -> CallableFunction { pub fn print_out_to_token_callable() -> CallableFunction {
print_out_to_token().into() print_out_to_token().into()
} }
pub fn print_out_to_token_input_names() -> Box<[&'static str]> {
print_out_to_token().input_names()
}
pub fn print_out_to_token_input_types() -> Box<[TypeId]> { pub fn print_out_to_token_input_types() -> Box<[TypeId]> {
print_out_to_token().input_types() print_out_to_token().input_types()
} }
@ -1125,7 +1185,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
&[core::any::TypeId::of::<FLOAT>()], Some(&["x: &mut FLOAT"]), &[core::any::TypeId::of::<FLOAT>()],
increment_token().into()); increment_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1144,6 +1204,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(increment_token()) Box::new(increment_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut FLOAT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<FLOAT>()].into_boxed_slice() new_vec![TypeId::of::<FLOAT>()].into_boxed_slice()
} }
@ -1151,6 +1214,9 @@ mod generate_tests {
pub fn increment_token_callable() -> CallableFunction { pub fn increment_token_callable() -> CallableFunction {
increment_token().into() increment_token().into()
} }
pub fn increment_token_input_names() -> Box<[&'static str]> {
increment_token().input_names()
}
pub fn increment_token_input_types() -> Box<[TypeId]> { pub fn increment_token_input_types() -> Box<[TypeId]> {
increment_token().input_types() increment_token().input_types()
} }
@ -1191,7 +1257,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
&[core::any::TypeId::of::<FLOAT>()], Some(&["x: &mut FLOAT"]), &[core::any::TypeId::of::<FLOAT>()],
increment_token().into()); increment_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1210,6 +1276,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(increment_token()) Box::new(increment_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut FLOAT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<FLOAT>()].into_boxed_slice() new_vec![TypeId::of::<FLOAT>()].into_boxed_slice()
} }
@ -1217,6 +1286,9 @@ mod generate_tests {
pub fn increment_token_callable() -> CallableFunction { pub fn increment_token_callable() -> CallableFunction {
increment_token().into() increment_token().into()
} }
pub fn increment_token_input_names() -> Box<[&'static str]> {
increment_token().input_names()
}
pub fn increment_token_input_types() -> Box<[TypeId]> { pub fn increment_token_input_types() -> Box<[TypeId]> {
increment_token().input_types() increment_token().input_types()
} }
@ -1278,7 +1350,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, m.set_fn("increment", FnNamespace::Internal, FnAccess::Public,
&[core::any::TypeId::of::<FLOAT>()], Some(&["x: &mut FLOAT"]), &[core::any::TypeId::of::<FLOAT>()],
increment_token().into()); increment_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1297,6 +1369,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(increment_token()) Box::new(increment_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut FLOAT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<FLOAT>()].into_boxed_slice() new_vec![TypeId::of::<FLOAT>()].into_boxed_slice()
} }
@ -1304,6 +1379,9 @@ mod generate_tests {
pub fn increment_token_callable() -> CallableFunction { pub fn increment_token_callable() -> CallableFunction {
increment_token().into() increment_token().into()
} }
pub fn increment_token_input_names() -> Box<[&'static str]> {
increment_token().input_names()
}
pub fn increment_token_input_types() -> Box<[TypeId]> { pub fn increment_token_input_types() -> Box<[TypeId]> {
increment_token().input_types() increment_token().input_types()
} }
@ -1363,7 +1441,7 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()], m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64"]), &[core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1382,6 +1460,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(int_foo_token()) Box::new(int_foo_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<u64>()].into_boxed_slice() new_vec![TypeId::of::<u64>()].into_boxed_slice()
} }
@ -1389,6 +1470,9 @@ mod generate_tests {
pub fn int_foo_token_callable() -> CallableFunction { pub fn int_foo_token_callable() -> CallableFunction {
int_foo_token().into() int_foo_token().into()
} }
pub fn int_foo_token_input_names() -> Box<[&'static str]> {
int_foo_token().input_names()
}
pub fn int_foo_token_input_types() -> Box<[TypeId]> { pub fn int_foo_token_input_types() -> Box<[TypeId]> {
int_foo_token().input_types() int_foo_token().input_types()
} }
@ -1426,9 +1510,9 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()], m.set_fn("square", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64"]), &[core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, &[core::any::TypeId::of::<u64>()], m.set_fn("get$square", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64"]), &[core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1447,6 +1531,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(int_foo_token()) Box::new(int_foo_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<u64>()].into_boxed_slice() new_vec![TypeId::of::<u64>()].into_boxed_slice()
} }
@ -1454,6 +1541,9 @@ mod generate_tests {
pub fn int_foo_token_callable() -> CallableFunction { pub fn int_foo_token_callable() -> CallableFunction {
int_foo_token().into() int_foo_token().into()
} }
pub fn int_foo_token_input_names() -> Box<[&'static str]> {
int_foo_token().input_names()
}
pub fn int_foo_token_input_types() -> Box<[TypeId]> { pub fn int_foo_token_input_types() -> Box<[TypeId]> {
int_foo_token().input_types() int_foo_token().input_types()
} }
@ -1491,9 +1581,8 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public, m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64", "y: u64"]),
&[core::any::TypeId::of::<u64>(), &[core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>()],
core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1513,6 +1602,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(int_foo_token()) Box::new(int_foo_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut u64", "y: u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<u64>(), TypeId::of::<u64>()].into_boxed_slice() new_vec![TypeId::of::<u64>(), TypeId::of::<u64>()].into_boxed_slice()
} }
@ -1520,6 +1612,9 @@ mod generate_tests {
pub fn int_foo_token_callable() -> CallableFunction { pub fn int_foo_token_callable() -> CallableFunction {
int_foo_token().into() int_foo_token().into()
} }
pub fn int_foo_token_input_names() -> Box<[&'static str]> {
int_foo_token().input_names()
}
pub fn int_foo_token_input_types() -> Box<[TypeId]> { pub fn int_foo_token_input_types() -> Box<[TypeId]> {
int_foo_token().input_types() int_foo_token().input_types()
} }
@ -1557,13 +1652,11 @@ mod generate_tests {
} }
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("set_sq", FnNamespace::Internal, FnAccess::Public, m.set_fn("set_sq", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64", "y: u64"]),
&[core::any::TypeId::of::<u64>(), &[core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>()],
core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public, m.set_fn("set$squared", FnNamespace::Internal, FnAccess::Public, Some(&["x: &mut u64", "y: u64"]),
&[core::any::TypeId::of::<u64>(), &[core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>()],
core::any::TypeId::of::<u64>()],
int_foo_token().into()); int_foo_token().into());
if flatten {} else {} if flatten {} else {}
} }
@ -1583,6 +1676,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(int_foo_token()) Box::new(int_foo_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut u64", "y: u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<u64>(), TypeId::of::<u64>()].into_boxed_slice() new_vec![TypeId::of::<u64>(), TypeId::of::<u64>()].into_boxed_slice()
} }
@ -1590,6 +1686,9 @@ mod generate_tests {
pub fn int_foo_token_callable() -> CallableFunction { pub fn int_foo_token_callable() -> CallableFunction {
int_foo_token().into() int_foo_token().into()
} }
pub fn int_foo_token_input_names() -> Box<[&'static str]> {
int_foo_token().input_names()
}
pub fn int_foo_token_input_types() -> Box<[TypeId]> { pub fn int_foo_token_input_types() -> Box<[TypeId]> {
int_foo_token().input_types() int_foo_token().input_types()
} }
@ -1628,6 +1727,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public, m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>()], core::any::TypeId::of::<u64>()],
get_by_index_token().into()); get_by_index_token().into());
@ -1649,6 +1749,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(get_by_index_token()) Box::new(get_by_index_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut MyCollection", "i: u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<MyCollection>(), new_vec![TypeId::of::<MyCollection>(),
TypeId::of::<u64>()].into_boxed_slice() TypeId::of::<u64>()].into_boxed_slice()
@ -1657,6 +1760,9 @@ mod generate_tests {
pub fn get_by_index_token_callable() -> CallableFunction { pub fn get_by_index_token_callable() -> CallableFunction {
get_by_index_token().into() get_by_index_token().into()
} }
pub fn get_by_index_token_input_names() -> Box<[&'static str]> {
get_by_index_token().input_names()
}
pub fn get_by_index_token_input_types() -> Box<[TypeId]> { pub fn get_by_index_token_input_types() -> Box<[TypeId]> {
get_by_index_token().input_types() get_by_index_token().input_types()
} }
@ -1695,10 +1801,12 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("get", FnNamespace::Internal, FnAccess::Public, m.set_fn("get", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>()], core::any::TypeId::of::<u64>()],
get_by_index_token().into()); get_by_index_token().into());
m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public, m.set_fn("index$get$", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>()], core::any::TypeId::of::<u64>()],
get_by_index_token().into()); get_by_index_token().into());
@ -1720,6 +1828,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(get_by_index_token()) Box::new(get_by_index_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut MyCollection", "i: u64"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<MyCollection>(), new_vec![TypeId::of::<MyCollection>(),
TypeId::of::<u64>()].into_boxed_slice() TypeId::of::<u64>()].into_boxed_slice()
@ -1728,6 +1839,9 @@ mod generate_tests {
pub fn get_by_index_token_callable() -> CallableFunction { pub fn get_by_index_token_callable() -> CallableFunction {
get_by_index_token().into() get_by_index_token().into()
} }
pub fn get_by_index_token_input_names() -> Box<[&'static str]> {
get_by_index_token().input_names()
}
pub fn get_by_index_token_input_types() -> Box<[TypeId]> { pub fn get_by_index_token_input_types() -> Box<[TypeId]> {
get_by_index_token().input_types() get_by_index_token().input_types()
} }
@ -1766,6 +1880,7 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public, m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64", "item: FLOAT"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>(),
core::any::TypeId::of::<FLOAT>()], core::any::TypeId::of::<FLOAT>()],
@ -1789,6 +1904,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(set_by_index_token()) Box::new(set_by_index_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut MyCollection", "i: u64", "item: FLOAT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<MyCollection>(), new_vec![TypeId::of::<MyCollection>(),
TypeId::of::<u64>(), TypeId::of::<u64>(),
@ -1798,6 +1916,9 @@ mod generate_tests {
pub fn set_by_index_token_callable() -> CallableFunction { pub fn set_by_index_token_callable() -> CallableFunction {
set_by_index_token().into() set_by_index_token().into()
} }
pub fn set_by_index_token_input_names() -> Box<[&'static str]> {
set_by_index_token().input_names()
}
pub fn set_by_index_token_input_types() -> Box<[TypeId]> { pub fn set_by_index_token_input_types() -> Box<[TypeId]> {
set_by_index_token().input_types() set_by_index_token().input_types()
} }
@ -1836,11 +1957,13 @@ mod generate_tests {
#[allow(unused_mut)] #[allow(unused_mut)]
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
m.set_fn("set", FnNamespace::Internal, FnAccess::Public, m.set_fn("set", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64", "item: FLOAT"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>(),
core::any::TypeId::of::<FLOAT>()], core::any::TypeId::of::<FLOAT>()],
set_by_index_token().into()); set_by_index_token().into());
m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public, m.set_fn("index$set$", FnNamespace::Internal, FnAccess::Public,
Some(&["x: &mut MyCollection", "i: u64", "item: FLOAT"]),
&[core::any::TypeId::of::<MyCollection>(), &[core::any::TypeId::of::<MyCollection>(),
core::any::TypeId::of::<u64>(), core::any::TypeId::of::<u64>(),
core::any::TypeId::of::<FLOAT>()], core::any::TypeId::of::<FLOAT>()],
@ -1864,6 +1987,9 @@ mod generate_tests {
fn clone_boxed(&self) -> Box<dyn PluginFunction> { fn clone_boxed(&self) -> Box<dyn PluginFunction> {
Box::new(set_by_index_token()) Box::new(set_by_index_token())
} }
fn input_names(&self) -> Box<[&'static str]> {
new_vec!["x: &mut MyCollection", "i: u64", "item: FLOAT"].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> { fn input_types(&self) -> Box<[TypeId]> {
new_vec![TypeId::of::<MyCollection>(), new_vec![TypeId::of::<MyCollection>(),
TypeId::of::<u64>(), TypeId::of::<u64>(),
@ -1873,6 +1999,9 @@ mod generate_tests {
pub fn set_by_index_token_callable() -> CallableFunction { pub fn set_by_index_token_callable() -> CallableFunction {
set_by_index_token().into() set_by_index_token().into()
} }
pub fn set_by_index_token_input_names() -> Box<[&'static str]> {
set_by_index_token().input_names()
}
pub fn set_by_index_token_input_types() -> Box<[TypeId]> { pub fn set_by_index_token_input_types() -> Box<[TypeId]> {
set_by_index_token().input_types() set_by_index_token().input_types()
} }

View File

@ -9,8 +9,6 @@ Keywords List
| `false` | boolean false literal | | no | | | `false` | boolean false literal | | no | |
| `let` | variable declaration | | no | | | `let` | variable declaration | | no | |
| `const` | constant declaration | | no | | | `const` | constant declaration | | no | |
| `is_def_var` | is a variable declared? | | yes | yes |
| `is_shared` | is a value shared? | [`no_closure`] | yes | no |
| `if` | if statement | | no | | | `if` | if statement | | no | |
| `else` | else block of if statement | | no | | | `else` | else block of if statement | | no | |
| `switch` | matching | | no | | | `switch` | matching | | no | |
@ -35,7 +33,6 @@ Keywords List
| `call` | call a [function pointer] | | yes | no | | `call` | call a [function pointer] | | yes | no |
| `curry` | curry a [function pointer] | | yes | no | | `curry` | curry a [function pointer] | | yes | no |
| `this` | reference to base object for method call | [`no_function`] | no | | | `this` | reference to base object for method call | [`no_function`] | no | |
| `is_def_fn` | is a scripted function defined? | [`no_function`] | yes | yes |
| `type_of` | get type name of value | | yes | yes | | `type_of` | get type name of value | | yes | yes |
| `print` | print value | | yes | yes | | `print` | print value | | yes | yes |
| `debug` | print value in debug format | | yes | yes | | `debug` | print value in debug format | | yes | yes |

View File

@ -42,6 +42,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");
println!("functions => print all functions defined");
println!("ast => print the last AST"); println!("ast => print the last AST");
println!("astu => print the last raw, un-optimized AST"); println!("astu => print the last raw, un-optimized AST");
println!(r"end a line with '\' to continue to the next line."); println!(r"end a line with '\' to continue to the next line.");
@ -133,6 +134,18 @@ fn main() {
println!("{:#?}\n", &ast); println!("{:#?}\n", &ast);
continue; continue;
} }
"functions" => {
// print a list of all registered functions
engine
.gen_fn_signatures(false)
.into_iter()
.for_each(|f| println!("{}", f));
main_ast
.iter_functions()
.for_each(|(_, _, _, _, f)| println!("{}", f));
println!();
continue;
}
_ => (), _ => (),
} }

View File

@ -100,7 +100,7 @@ impl fmt::Display for ScriptFnDef {
.iter() .iter()
.map(|s| s.as_str()) .map(|s| s.as_str())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(",") .join(", ")
) )
} }
} }

View File

@ -95,24 +95,25 @@ impl Imports {
self.0.as_mut().unwrap().truncate(size); self.0.as_mut().unwrap().truncate(size);
} }
} }
/// Get an iterator to this stack of imported modules. /// Get an iterator to this stack of imported modules in reverse order.
#[allow(dead_code)] #[allow(dead_code)]
pub fn iter(&self) -> impl Iterator<Item = (&str, Shared<Module>)> { pub fn iter(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
self.0.iter().flat_map(|lib| { self.0.iter().flat_map(|lib| {
lib.iter() lib.iter()
.rev()
.map(|(name, module)| (name.as_str(), module.clone())) .map(|(name, module)| (name.as_str(), module.clone()))
}) })
} }
/// Get an iterator to this stack of imported modules. /// Get an iterator to this stack of imported modules in reverse order.
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn iter_raw<'a>( pub(crate) fn iter_raw<'a>(
&'a self, &'a self,
) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> + 'a { ) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> + 'a {
self.0.iter().flat_map(|lib| lib.iter().cloned()) self.0.iter().flat_map(|lib| lib.iter().rev().cloned())
} }
/// Get a consuming iterator to this stack of imported modules. /// Get a consuming iterator to this stack of imported modules in reverse order.
pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> { pub fn into_iter(self) -> impl Iterator<Item = (ImmutableString, Shared<Module>)> {
self.0.into_iter().flat_map(|lib| lib.into_iter()) self.0.into_iter().flat_map(|lib| lib.into_iter().rev())
} }
/// Add a stream of imported modules. /// Add a stream of imported modules.
pub fn extend(&mut self, stream: impl Iterator<Item = (ImmutableString, Shared<Module>)>) { pub fn extend(&mut self, stream: impl Iterator<Item = (ImmutableString, Shared<Module>)>) {

View File

@ -1515,7 +1515,7 @@ impl Engine {
.into() .into()
}); });
} }
/// Call a script function defined in an [`AST`] with multiple `Dynamic` arguments /// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments
/// and optionally a value for binding to the `this` pointer. /// and optionally a value for binding to the `this` pointer.
/// ///
/// ## WARNING /// ## WARNING
@ -1578,7 +1578,7 @@ impl Engine {
self.call_fn_dynamic_raw(scope, &[lib.as_ref()], name, &mut this_ptr, args.as_mut()) self.call_fn_dynamic_raw(scope, &[lib.as_ref()], name, &mut this_ptr, args.as_mut())
} }
/// Call a script function defined in an [`AST`] with multiple `Dynamic` arguments. /// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments.
/// ///
/// ## WARNING /// ## WARNING
/// ///
@ -1646,6 +1646,27 @@ impl Engine {
let stmt = crate::stdlib::mem::take(ast.statements_mut()); let stmt = crate::stdlib::mem::take(ast.statements_mut());
crate::optimize::optimize_into_ast(self, scope, stmt, lib, optimization_level) crate::optimize::optimize_into_ast(self, scope, stmt, lib, optimization_level)
} }
/// Generate a list of all registered functions.
///
/// The ordering is:
/// 1) Functions registered into the global namespace
/// 2) Functions in registered sub-modules
/// 3) Functions in packages
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
let mut signatures: Vec<_> = Default::default();
signatures.extend(self.global_namespace.gen_fn_signatures());
self.global_sub_modules.iter().for_each(|(name, m)| {
signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f)))
});
if include_packages {
signatures.extend(self.packages.gen_fn_signatures());
}
signatures
}
/// Provide a callback that will be invoked before each variable access. /// Provide a callback that will be invoked before each variable access.
/// ///
/// ## Return Value of Callback /// ## Return Value of Callback

View File

@ -187,7 +187,7 @@ macro_rules! def_register {
{ {
#[inline] #[inline]
fn register_fn(&mut self, name: &str, f: FN) -> &mut Self { fn register_fn(&mut self, name: &str, f: FN) -> &mut Self {
self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
&[$(map_type_id::<$par>()),*], &[$(map_type_id::<$par>()),*],
CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*)) CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*))
); );
@ -202,7 +202,7 @@ macro_rules! def_register {
{ {
#[inline] #[inline]
fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self { fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self {
self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
&[$(map_type_id::<$par>()),*], &[$(map_type_id::<$par>()),*],
CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*)) CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*))
); );

View File

@ -79,7 +79,31 @@ pub struct FuncInfo {
/// Number of parameters. /// Number of parameters.
pub params: usize, pub params: usize,
/// Parameter types (if applicable). /// Parameter types (if applicable).
pub types: Option<StaticVec<TypeId>>, pub param_types: Option<StaticVec<TypeId>>,
/// Parameter names (if available).
pub param_names: Option<StaticVec<ImmutableString>>,
}
impl FuncInfo {
/// Generate a signature of the function.
pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.name);
if let Some(ref names) = self.param_names {
let params: Vec<_> = names.iter().map(ImmutableString::to_string).collect();
sig.push_str(&params.join(", "));
} else {
for x in 0..self.params {
sig.push_str("_");
if x < self.params - 1 {
sig.push_str(", ");
}
}
}
sig.push_str(")");
sig
}
} }
/// A module which may contain variables, sub-modules, external Rust functions, /// A module which may contain variables, sub-modules, external Rust functions,
@ -230,6 +254,14 @@ impl Module {
self.indexed self.indexed
} }
/// Generate signatures for all the functions in the module.
pub fn gen_fn_signatures<'a>(&'a self) -> impl Iterator<Item = String> + 'a {
self.functions
.values()
.filter(|FuncInfo { access, .. }| !access.is_private())
.map(FuncInfo::gen_signature)
}
/// Does a variable exist in the module? /// Does a variable exist in the module?
/// ///
/// # Example /// # Example
@ -329,7 +361,8 @@ impl Module {
namespace: FnNamespace::Internal, namespace: FnNamespace::Internal,
access: fn_def.access, access: fn_def.access,
params: num_params, params: num_params,
types: None, param_types: None,
param_names: Some(fn_def.params.clone()),
func: fn_def.into(), func: fn_def.into(),
}, },
); );
@ -450,6 +483,17 @@ impl Module {
} }
} }
/// Update the parameter names and types in a registered function.
///
/// The [`u64`] hash is calculated either by the function [`crate::calc_native_fn_hash`] or
/// the function [`crate::calc_script_fn_hash`].
pub fn update_fn_param_names(&mut self, hash_fn: u64, arg_names: &[&str]) -> &mut Self {
if let Some(f) = self.functions.get_mut(&hash_fn) {
f.param_names = Some(arg_names.iter().map(|&n| n.into()).collect());
}
self
}
/// Set a Rust function into the module, returning a hash key. /// Set a Rust function into the module, returning a hash key.
/// ///
/// If there is an existing Rust function of the same hash, it is replaced. /// If there is an existing Rust function of the same hash, it is replaced.
@ -462,6 +506,7 @@ impl Module {
name: impl Into<String>, name: impl Into<String>,
namespace: FnNamespace, namespace: FnNamespace,
access: FnAccess, access: FnAccess,
arg_names: Option<&[&str]>,
arg_types: &[TypeId], arg_types: &[TypeId],
func: CallableFunction, func: CallableFunction,
) -> u64 { ) -> u64 {
@ -488,7 +533,8 @@ impl Module {
namespace, namespace,
access, access,
params: params.len(), params: params.len(),
types: Some(params), param_types: Some(params),
param_names: arg_names.map(|p| p.iter().map(|&v| v.into()).collect()),
func: func.into(), func: func.into(),
}, },
); );
@ -576,6 +622,7 @@ impl Module {
name, name,
namespace, namespace,
access, access,
None,
arg_types, arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -606,6 +653,7 @@ impl Module {
name, name,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_pure(Box::new(f)), CallableFunction::from_pure(Box::new(f)),
) )
@ -638,6 +686,7 @@ impl Module {
name, name,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_pure(Box::new(f)), CallableFunction::from_pure(Box::new(f)),
) )
@ -673,6 +722,7 @@ impl Module {
name, name,
namespace, namespace,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -738,6 +788,7 @@ impl Module {
name, name,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_pure(Box::new(f)), CallableFunction::from_pure(Box::new(f)),
) )
@ -780,6 +831,7 @@ impl Module {
name, name,
namespace, namespace,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -900,6 +952,7 @@ impl Module {
name, name,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_pure(Box::new(f)), CallableFunction::from_pure(Box::new(f)),
) )
@ -948,6 +1001,7 @@ impl Module {
name, name,
namespace, namespace,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -1008,6 +1062,7 @@ impl Module {
crate::engine::FN_IDX_SET, crate::engine::FN_IDX_SET,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -1100,6 +1155,7 @@ impl Module {
name, name,
FnNamespace::Internal, FnNamespace::Internal,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_pure(Box::new(f)), CallableFunction::from_pure(Box::new(f)),
) )
@ -1155,6 +1211,7 @@ impl Module {
name, name,
namespace, namespace,
FnAccess::Public, FnAccess::Public,
None,
&arg_types, &arg_types,
CallableFunction::from_method(Box::new(f)), CallableFunction::from_method(Box::new(f)),
) )
@ -1569,7 +1626,7 @@ impl Module {
name, name,
namespace, namespace,
params, params,
types, param_types: types,
func, func,
.. ..
}, },

View File

@ -48,7 +48,8 @@ macro_rules! reg_range {
($lib:expr, $x:expr, $( $y:ty ),*) => ( ($lib:expr, $x:expr, $( $y:ty ),*) => (
$( $(
$lib.set_iterator::<Range<$y>>(); $lib.set_iterator::<Range<$y>>();
$lib.set_fn_2($x, get_range::<$y>); let hash = $lib.set_fn_2($x, get_range::<$y>);
$lib.update_fn_param_names(hash, &[concat!("from: ", stringify!($y)), concat!("to: ", stringify!($y))]);
)* )*
) )
} }
@ -59,14 +60,16 @@ macro_rules! reg_step {
($lib:expr, $x:expr, $( $y:ty ),*) => ( ($lib:expr, $x:expr, $( $y:ty ),*) => (
$( $(
$lib.set_iterator::<StepRange<$y>>(); $lib.set_iterator::<StepRange<$y>>();
$lib.set_fn_3($x, get_step_range::<$y>); let hash = $lib.set_fn_3($x, get_step_range::<$y>);
$lib.update_fn_param_names(hash, &[concat!("from: ", stringify!($y)), concat!("to: ", stringify!($y)), concat!("step: ", stringify!($y))]);
)* )*
) )
} }
def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
lib.set_iterator::<Range<INT>>(); lib.set_iterator::<Range<INT>>();
lib.set_fn_2("range", get_range::<INT>); let hash = lib.set_fn_2("range", get_range::<INT>);
lib.update_fn_param_names(hash, &["from: INT", "to: INT"]);
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))] #[cfg(not(feature = "only_i64"))]
@ -79,7 +82,8 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
} }
lib.set_iterator::<StepRange<INT>>(); lib.set_iterator::<StepRange<INT>>();
lib.set_fn_3("range", get_step_range::<INT>); let hash = lib.set_fn_3("range", get_step_range::<INT>);
lib.update_fn_param_names(hash, &["from: INT", "to: INT", "step: INT"]);
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))] #[cfg(not(feature = "only_i64"))]

View File

@ -87,6 +87,15 @@ impl PackagesCollection {
.as_ref() .as_ref()
.and_then(|x| x.iter().find_map(|p| p.get_iter(id))) .and_then(|x| x.iter().find_map(|p| p.get_iter(id)))
} }
/// Get an iterator over all the packages in the [`PackagesCollection`].
pub(crate) fn iter(&self) -> impl Iterator<Item = &PackageLibrary> {
self.0.iter().flat_map(|p| p.iter())
}
/// Generate signatures for all the functions in the [`PackagesCollection`].
pub fn gen_fn_signatures<'a>(&'a self) -> impl Iterator<Item = String> + 'a {
self.iter().flat_map(|m| m.gen_fn_signatures())
}
} }
/// Macro that makes it easy to define a _package_ (which is basically a shared module) /// Macro that makes it easy to define a _package_ (which is basically a shared module)

View File

@ -33,6 +33,9 @@ pub trait PluginFunction {
/// Convert a plugin function into a boxed trait object. /// Convert a plugin function into a boxed trait object.
fn clone_boxed(&self) -> Box<dyn PluginFunction>; fn clone_boxed(&self) -> Box<dyn PluginFunction>;
/// Return a boxed slice of the names of the function's parameters.
fn input_names(&self) -> Box<[&'static str]>;
/// Return a boxed slice of type ID's of the function's parameters. /// Return a boxed slice of type ID's of the function's parameters.
fn input_types(&self) -> Box<[TypeId]>; fn input_types(&self) -> Box<[TypeId]>;
} }

View File

@ -2,7 +2,7 @@
use crate::engine::{ use crate::engine::{
KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
}; };
use crate::stdlib::{ use crate::stdlib::{
borrow::Cow, borrow::Cow,
@ -538,11 +538,7 @@ impl Token {
| "async" | "await" | "yield" => Reserved(syntax.into()), | "async" | "await" | "yield" => Reserved(syntax.into()),
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR | KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_THIS => Reserved(syntax.into()),
| KEYWORD_IS_DEF_FN | KEYWORD_THIS => Reserved(syntax.into()),
#[cfg(not(feature = "no_closure"))]
crate::engine::KEYWORD_IS_SHARED => Reserved(syntax.into()),
_ => return None, _ => return None,
}) })
@ -1513,12 +1509,8 @@ fn get_identifier(
#[inline(always)] #[inline(always)]
pub fn is_keyword_function(name: &str) -> bool { pub fn is_keyword_function(name: &str) -> bool {
match name { match name {
#[cfg(not(feature = "no_closure"))]
crate::engine::KEYWORD_IS_SHARED => true,
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => { | KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY => true,
true
}
_ => false, _ => false,
} }
} }
@ -1528,8 +1520,7 @@ pub fn is_keyword_function(name: &str) -> bool {
#[inline(always)] #[inline(always)]
pub fn can_override_keyword(name: &str) -> bool { pub fn can_override_keyword(name: &str) -> bool {
match name { match name {
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR => true,
| KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => true,
_ => false, _ => false,
} }
} }