diff --git a/Cargo.toml b/Cargo.toml index b7ecc4f3..b16375d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ categories = ["no-std", "embedded", "wasm", "parser-implementations"] smallvec = { version = "1.6", default-features = false, features = ["union"] } ahash = { version = "0.7", default-features = false } num-traits = { version = "0.2", default_features = false } -rhai_codegen = { version = "0.3.4", path = "codegen" } +rhai_codegen = { version = "0.3.4", path = "codegen", features = ["metadata"] } [features] default = [] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 1170ea08..94b0b2cc 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -11,6 +11,10 @@ license = "MIT OR Apache-2.0" [lib] proc-macro = true +[features] +default = [] +metadata = [] + [dev-dependencies] rhai = { path = "..", version = "^0.19.15" } trybuild = "1" diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 03d42400..c8c336e6 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -650,6 +650,7 @@ impl ExportedFn { let mut unpack_statements: Vec = Vec::new(); let mut unpack_exprs: Vec = Vec::new(); + #[cfg(feature = "metadata")] let mut input_type_names: Vec = Vec::new(); let mut input_type_exprs: Vec = Vec::new(); @@ -671,6 +672,7 @@ impl ExportedFn { let var = syn::Ident::new("arg0", proc_macro2::Span::call_site()); match first_arg { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => { + #[cfg(feature = "metadata")] 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(), @@ -699,6 +701,7 @@ impl ExportedFn { .unwrap(), ); } + #[cfg(feature = "metadata")] input_type_names.push(arg_name); input_type_exprs.push( syn::parse2::(quote_spanned!(arg_type.span() => @@ -726,6 +729,7 @@ impl ExportedFn { let is_ref; match arg { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => { + #[cfg(feature = "metadata")] let arg_name = format!("{}: {}", pat.to_token_stream(), print_type(ty)); let arg_type = ty.as_ref(); let downcast_span = match flatten_type_groups(arg_type) { @@ -765,6 +769,7 @@ impl ExportedFn { }) .unwrap(), ); + #[cfg(feature = "metadata")] input_type_names.push(arg_name); if !is_string { input_type_exprs.push( @@ -817,9 +822,17 @@ impl ExportedFn { }; let type_name = syn::Ident::new(on_type_name, proc_macro2::Span::call_site()); + + #[cfg(feature = "metadata")] + let param_names = quote! { + pub const PARAM_NAMES: &'static [&'static str] = &[#(#input_type_names,)* #return_type]; + }; + #[cfg(not(feature = "metadata"))] + let param_names = quote! {}; + quote! { impl #type_name { - pub const PARAM_NAMES: &'static [&'static str] = &[#(#input_type_names,)* #return_type]; + #param_names #[inline(always)] pub fn param_types() -> [TypeId; #arg_count] { [#(#input_type_exprs),*] } } impl PluginFunction for #type_name { diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index e6af8fe2..4ab0f628 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -330,11 +330,19 @@ pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream match crate::register::parse_register_macro(args) { Ok((module_expr, export_name, rust_mod_path)) => { let gen_mod_path = crate::register::generated_module_path(&rust_mod_path); + + #[cfg(feature = "metadata")] + let param_names = quote! { + Some(#gen_mod_path::Token::PARAM_NAMES) + }; + #[cfg(not(feature = "metadata"))] + let param_names = quote! { None }; + proc_macro::TokenStream::from(quote! { - #module_expr.set_fn(#export_name, FnNamespace::Internal, FnAccess::Public, - Some(#gen_mod_path::Token::PARAM_NAMES), - &#gen_mod_path::Token::param_types(), - #gen_mod_path::Token().into()); + #module_expr.set_plugin_fn(#export_name, FnNamespace::Internal, FnAccess::Public, + #param_names, + &#gen_mod_path::Token::param_types(), + #gen_mod_path::Token()); }) } Err(e) => e.to_compile_error().into(), @@ -371,11 +379,19 @@ pub fn set_exported_global_fn(args: proc_macro::TokenStream) -> proc_macro::Toke match crate::register::parse_register_macro(args) { Ok((module_expr, export_name, rust_mod_path)) => { let gen_mod_path = crate::register::generated_module_path(&rust_mod_path); + + #[cfg(feature = "metadata")] + let param_names = quote! { + Some(#gen_mod_path::Token::PARAM_NAMES) + }; + #[cfg(not(feature = "metadata"))] + let param_names = quote! { None }; + proc_macro::TokenStream::from(quote! { - #module_expr.set_fn(#export_name, FnNamespace::Global, FnAccess::Public, - Some(#gen_mod_path::Token::PARAM_NAMES), - &#gen_mod_path::Token::param_types(), - #gen_mod_path::Token().into()); + #module_expr.set_plugin_fn(#export_name, FnNamespace::Global, FnAccess::Public, + #param_names, + &#gen_mod_path::Token::param_types(), + #gen_mod_path::Token()); }) } Err(e) => e.to_compile_error().into(), diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index 11c8d1de..c21384aa 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -154,11 +154,18 @@ pub fn generate_body( }, fn_literal.span(), ); + + #[cfg(feature = "metadata")] + let param_names = quote! { + Some(#fn_token_name::PARAM_NAMES) + }; + #[cfg(not(feature = "metadata"))] + let param_names = quote! { None }; + set_fn_statements.push( syn::parse2::(quote! { - m.set_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public, - Some(#fn_token_name::PARAM_NAMES), &[#(#fn_input_types),*], - #fn_token_name().into()); + m.set_plugin_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public, + #param_names, &[#(#fn_input_types),*], #fn_token_name()); }) .unwrap(), ); diff --git a/codegen/src/test/module.rs b/codegen/src/test/module.rs index fdf4cf12..22f75fdf 100644 --- a/codegen/src/test/module.rs +++ b/codegen/src/test/module.rs @@ -297,9 +297,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, + m.set_plugin_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, Some(get_mystic_number_token::PARAM_NAMES), &[], - get_mystic_number_token().into()); + get_mystic_number_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -351,9 +351,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("add_one_to", FnNamespace::Global, FnAccess::Public, + m.set_plugin_fn("add_one_to", FnNamespace::Global, FnAccess::Public, Some(add_one_to_token::PARAM_NAMES), &[TypeId::of::()], - add_one_to_token().into()); + add_one_to_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -405,9 +405,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("add_one_to", FnNamespace::Internal, FnAccess::Public, Some(add_one_to_token::PARAM_NAMES), + m.set_plugin_fn("add_one_to", FnNamespace::Internal, FnAccess::Public, Some(add_one_to_token::PARAM_NAMES), &[TypeId::of::()], - add_one_to_token().into()); + add_one_to_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -470,12 +470,12 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(add_one_to_token::PARAM_NAMES), + m.set_plugin_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(add_one_to_token::PARAM_NAMES), &[TypeId::of::()], - add_one_to_token().into()); - m.set_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(add_n_to_token::PARAM_NAMES), + add_one_to_token()); + m.set_plugin_fn("add_n", FnNamespace::Internal, FnAccess::Public, Some(add_n_to_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - add_n_to_token().into()); + add_n_to_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -545,9 +545,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), + m.set_plugin_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - add_together_token().into()); + add_together_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -601,15 +601,15 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("add", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), + m.set_plugin_fn("add", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - add_together_token().into()); - m.set_fn("+", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), + add_together_token()); + m.set_plugin_fn("+", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - add_together_token().into()); - m.set_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), + add_together_token()); + m.set_plugin_fn("add_together", FnNamespace::Internal, FnAccess::Public, Some(add_together_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - add_together_token().into()); + add_together_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -844,9 +844,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, + m.set_plugin_fn("get_mystic_number", FnNamespace::Internal, FnAccess::Public, Some(get_mystic_number_token::PARAM_NAMES), &[], - get_mystic_number_token().into()); + get_mystic_number_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -928,9 +928,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, Some(print_out_to_token::PARAM_NAMES), + m.set_plugin_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, Some(print_out_to_token::PARAM_NAMES), &[TypeId::of::()], - print_out_to_token().into()); + print_out_to_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -982,9 +982,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, Some(print_out_to_token::PARAM_NAMES), + m.set_plugin_fn("print_out_to", FnNamespace::Internal, FnAccess::Public, Some(print_out_to_token::PARAM_NAMES), &[TypeId::of::()], - print_out_to_token().into()); + print_out_to_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1037,9 +1037,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("foo", FnNamespace::Internal, FnAccess::Public, Some(foo_token::PARAM_NAMES), + m.set_plugin_fn("foo", FnNamespace::Internal, FnAccess::Public, Some(foo_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - foo_token().into()); + foo_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1092,9 +1092,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), + m.set_plugin_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), &[TypeId::of::()], - increment_token().into()); + increment_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1154,9 +1154,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), + m.set_plugin_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), &[TypeId::of::()], - increment_token().into()); + increment_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1237,9 +1237,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), + m.set_plugin_fn("increment", FnNamespace::Internal, FnAccess::Public, Some(increment_token::PARAM_NAMES), &[TypeId::of::()], - increment_token().into()); + increment_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1319,9 +1319,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("get$square", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + m.set_plugin_fn("get$square", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::()], - int_foo_token().into()); + int_foo_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1379,12 +1379,12 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("square", FnNamespace::Internal, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + m.set_plugin_fn("square", FnNamespace::Internal, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::()], - int_foo_token().into()); - m.set_fn("get$square", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + int_foo_token()); + m.set_plugin_fn("get$square", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::()], - int_foo_token().into()); + int_foo_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1442,9 +1442,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("set$squared", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + m.set_plugin_fn("set$squared", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - int_foo_token().into()); + int_foo_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1503,12 +1503,12 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("set_sq", FnNamespace::Internal, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + m.set_plugin_fn("set_sq", FnNamespace::Internal, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - int_foo_token().into()); - m.set_fn("set$squared", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), + int_foo_token()); + m.set_plugin_fn("set$squared", FnNamespace::Global, FnAccess::Public, Some(int_foo_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - int_foo_token().into()); + int_foo_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1567,9 +1567,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("index$get$", FnNamespace::Global, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), + m.set_plugin_fn("index$get$", FnNamespace::Global, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - get_by_index_token().into()); + get_by_index_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1628,12 +1628,12 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("get", FnNamespace::Internal, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), + m.set_plugin_fn("get", FnNamespace::Internal, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - get_by_index_token().into()); - m.set_fn("index$get$", FnNamespace::Global, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), + get_by_index_token()); + m.set_plugin_fn("index$get$", FnNamespace::Global, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::()], - get_by_index_token().into()); + get_by_index_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1692,9 +1692,9 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("index$set$", FnNamespace::Global, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), + m.set_plugin_fn("index$set$", FnNamespace::Global, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::(), TypeId::of::()], - set_by_index_token().into()); + set_by_index_token()); if flatten {} else {} } #[allow(non_camel_case_types)] @@ -1754,12 +1754,12 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { - m.set_fn("set", FnNamespace::Internal, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), + m.set_plugin_fn("set", FnNamespace::Internal, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::(), TypeId::of::()], - set_by_index_token().into()); - m.set_fn("index$set$", FnNamespace::Global, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), + set_by_index_token()); + m.set_plugin_fn("index$set$", FnNamespace::Global, FnAccess::Public, Some(set_by_index_token::PARAM_NAMES), &[TypeId::of::(), TypeId::of::(), TypeId::of::()], - set_by_index_token().into()); + set_by_index_token()); if flatten {} else {} } #[allow(non_camel_case_types)] diff --git a/src/module/mod.rs b/src/module/mod.rs index e0d9a60b..49e2a665 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -4,6 +4,7 @@ use crate::ast::{FnAccess, Ident}; use crate::dynamic::Variant; use crate::fn_native::{shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync}; use crate::fn_register::RegisterNativeFunction; +use crate::plugin::PluginFunction; use crate::stdlib::{ any::TypeId, boxed::Box, @@ -644,6 +645,24 @@ impl Module { self } + /// Remap type ID. + #[inline(always)] + fn map_type(map: bool, type_id: TypeId) -> TypeId { + if !map { + return type_id; + } + if type_id == TypeId::of::<&str>() { + // Map &str to ImmutableString + return TypeId::of::(); + } + if type_id == TypeId::of::() { + // Map String to ImmutableString + return TypeId::of::(); + } + + type_id + } + /// 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. @@ -663,31 +682,12 @@ impl Module { ) -> u64 { let is_method = func.is_method(); - let param_types = arg_types + let param_types: StaticVec<_> = arg_types .iter() .cloned() .enumerate() - .map(|(i, type_id)| { - if !is_method || i > 0 { - if type_id == TypeId::of::<&str>() { - // Map &str to ImmutableString - TypeId::of::() - } else if type_id == TypeId::of::() { - // Map String to ImmutableString - TypeId::of::() - } else { - type_id - } - } else { - // Do not map &mut parameter - type_id - } - }) - .collect::>(); - - let hash_fn = calc_native_fn_hash(empty(), &name, ¶m_types); - - let name = self.interned_strings.get(name); + .map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id)) + .collect(); #[cfg(feature = "metadata")] let param_names = _arg_names @@ -696,10 +696,67 @@ impl Module { .map(|&arg| self.interned_strings.get(arg)) .collect(); + let hash_fn = calc_native_fn_hash(empty(), &name, ¶m_types); + self.functions.insert( hash_fn, Box::new(FuncInfo { - name, + name: self.interned_strings.get(name), + namespace, + access, + params: param_types.len(), + param_types, + #[cfg(feature = "metadata")] + param_names, + func, + }), + ); + + self.indexed = false; + self.contains_indexed_global_functions = false; + + hash_fn + } + + /// Set a plugin function into the [`Module`], returning a hash key. + /// + /// If there is an existing Rust function of the same hash, it is replaced. + /// + /// # WARNING - Low Level API + /// + /// This function is very low level. It is intended for plugins system use only. + #[inline(always)] + pub fn set_plugin_fn( + &mut self, + name: impl AsRef + Into, + namespace: FnNamespace, + access: FnAccess, + _arg_names: Option<&[&str]>, + arg_types: &[TypeId], + func: impl PluginFunction + 'static, + ) -> u64 { + let is_method = func.is_method_call(); + + let param_types: StaticVec<_> = arg_types + .iter() + .cloned() + .enumerate() + .map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id)) + .collect(); + + #[cfg(feature = "metadata")] + let param_names = _arg_names + .iter() + .flat_map(|p| p.iter()) + .map(|&arg| self.interned_strings.get(arg)) + .collect(); + + let hash_fn = calc_native_fn_hash(empty(), &name, ¶m_types); + + self.functions.insert( + hash_fn, + Box::new(FuncInfo { + name: self.interned_strings.get(name), namespace, access, params: param_types.len(),