From 72334f0c4277db7dc0f21bd02be12402fd4d46f8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 20 Feb 2021 14:05:47 +0800 Subject: [PATCH 1/8] Lower release stack overflow protection limit. --- src/engine.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index b5586849..ee54e8bd 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -185,10 +185,10 @@ pub const MAX_FUNCTION_EXPR_DEPTH: usize = 16; #[cfg(not(feature = "unchecked"))] #[cfg(not(debug_assertions))] #[cfg(not(feature = "no_function"))] -pub const MAX_CALL_STACK_DEPTH: usize = 128; +pub const MAX_CALL_STACK_DEPTH: usize = 64; #[cfg(not(feature = "unchecked"))] #[cfg(not(debug_assertions))] -pub const MAX_EXPR_DEPTH: usize = 128; +pub const MAX_EXPR_DEPTH: usize = 64; #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_function"))] #[cfg(not(debug_assertions))] From 54e26059dc660e01307995734ba24f4c01d211e7 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 20 Feb 2021 14:32:37 +0800 Subject: [PATCH 2/8] Set correct position for system errors inside function calls. --- src/fn_call.rs | 72 ++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 98251113..13ee3102 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -364,6 +364,27 @@ impl Engine { pos: Position, level: usize, ) -> Result> { + #[inline(always)] + fn make_error( + name: String, + fn_def: &crate::ast::ScriptFnDef, + state: &State, + err: Box, + pos: Position, + ) -> Result> { + Err(Box::new(EvalAltResult::ErrorInFunctionCall( + name, + fn_def + .lib + .as_ref() + .and_then(|m| m.id()) + .unwrap_or_else(|| state.source.as_ref().map_or_else(|| "", |s| s.as_str())) + .to_string(), + err, + pos, + ))) + } + self.inc_operations(state, pos)?; // Check for stack overflow @@ -421,48 +442,23 @@ impl Engine { .or_else(|err| match *err { // Convert return statement to return value EvalAltResult::Return(x, _) => Ok(x), + // Error in sub function call EvalAltResult::ErrorInFunctionCall(name, src, err, _) => { - EvalAltResult::ErrorInFunctionCall( - format!( - "{}{} < {}", - name, - if src.is_empty() { - "".to_string() - } else { - format!(" @ '{}'", src) - }, - fn_def.name - ), - fn_def - .lib - .as_ref() - .map(|m| m.id()) - .flatten() - .or_else(|| state.source.as_ref().map(|s| s.as_str())) - .unwrap_or("") - .to_string(), - err, - pos, - ) - .into() + let fn_name = if src.is_empty() { + format!("{} < {}", name, fn_def.name) + } else { + format!("{} @ '{}' < {}", name, src, fn_def.name) + }; + + make_error(fn_name, fn_def, state, err, pos) } // System errors are passed straight-through - err if err.is_system_exception() => Err(Box::new(err)), + mut err if err.is_system_exception() => Err(Box::new({ + err.set_position(pos); + err + })), // Other errors are wrapped in `ErrorInFunctionCall` - _ => EvalAltResult::ErrorInFunctionCall( - fn_def.name.to_string(), - fn_def - .lib - .as_ref() - .map(|m| m.id()) - .flatten() - .or_else(|| state.source.as_ref().map(|s| s.as_str())) - .unwrap_or("") - .to_string(), - err, - pos, - ) - .into(), + _ => make_error(fn_def.name.to_string(), fn_def, state, err, pos), }); // Remove all local variables From 03c31a969afae9f98451b852c85372d2bfb8932e Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 20 Feb 2021 23:46:25 +0800 Subject: [PATCH 3/8] Refine examples. --- examples/arrays_and_structs.rs | 32 +++++++++++++++++++--------- examples/custom_types_and_methods.rs | 12 +++++++++-- examples/hello.rs | 2 ++ examples/reuse_scope.rs | 10 +++++++-- examples/serde.rs | 2 +- examples/strings.rs | 10 ++++----- examples/threading.rs | 10 ++++----- 7 files changed, 53 insertions(+), 25 deletions(-) diff --git a/examples/arrays_and_structs.rs b/examples/arrays_and_structs.rs index 094a7d08..aac28801 100644 --- a/examples/arrays_and_structs.rs +++ b/examples/arrays_and_structs.rs @@ -9,7 +9,6 @@ impl TestStruct { pub fn update(&mut self) { self.x += 1000; } - pub fn new() -> Self { Self { x: 1 } } @@ -25,17 +24,30 @@ fn main() -> Result<(), Box> { .register_fn("new_ts", TestStruct::new) .register_fn("update", TestStruct::update); - println!( - "{:?}", - engine.eval::("let x = new_ts(); x.update(); x")? - ); - println!( - "{:?}", - engine.eval::("let x = [new_ts()]; x[0].update(); x[0]")? - ); + let result = engine.eval::( + r" + let x = new_ts(); + x.update(); + x + ", + )?; + + println!("{:?}", result); + + let result = engine.eval::( + r" + let x = [ new_ts() ]; + x[0].update(); + x[0] + ", + )?; + + println!("{:?}", result); Ok(()) } #[cfg(any(feature = "no_index", feature = "no_object"))] -fn main() {} +fn main() { + panic!("This example does not run under 'no_index' or 'no_object'.") +} diff --git a/examples/custom_types_and_methods.rs b/examples/custom_types_and_methods.rs index c48a7fde..5d494fd3 100644 --- a/examples/custom_types_and_methods.rs +++ b/examples/custom_types_and_methods.rs @@ -24,7 +24,13 @@ fn main() -> Result<(), Box> { .register_fn("new_ts", TestStruct::new) .register_fn("update", TestStruct::update); - let result = engine.eval::("let x = new_ts(); x.update(); x")?; + let result = engine.eval::( + r" + let x = new_ts(); + x.update(); + x + ", + )?; println!("result: {}", result.x); // prints 1001 @@ -32,4 +38,6 @@ fn main() -> Result<(), Box> { } #[cfg(feature = "no_object")] -fn main() {} +fn main() { + panic!("This example does not run under 'no_object'."); +} diff --git a/examples/hello.rs b/examples/hello.rs index 00913e2c..4133cd3f 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -3,6 +3,8 @@ use rhai::{Engine, EvalAltResult, INT}; fn main() -> Result<(), Box> { let engine = Engine::new(); + engine.consume(r#"print("hello, world!")"#)?; + let result = engine.eval::("40 + 2")?; println!("Answer: {}", result); // prints 42 diff --git a/examples/reuse_scope.rs b/examples/reuse_scope.rs index a762ac8a..e7446e55 100644 --- a/examples/reuse_scope.rs +++ b/examples/reuse_scope.rs @@ -6,9 +6,15 @@ fn main() -> Result<(), Box> { engine.eval_with_scope::<()>(&mut scope, "let x = 4 + 5")?; - let result = engine.eval_with_scope::(&mut scope, "x")?; + println!("x = {}", scope.get_value::("x").unwrap()); - println!("result: {}", result); + for _ in 0..10 { + let result = engine.eval_with_scope::(&mut scope, "x += 1; x")?; + + println!("result: {}", result); + } + + println!("x = {}", scope.get_value::("x").unwrap()); Ok(()) } diff --git a/examples/serde.rs b/examples/serde.rs index eca31453..bf40499d 100644 --- a/examples/serde.rs +++ b/examples/serde.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "serde"))] fn main() { - println!(r#"This example requires the "serde" feature which is not enabled by default."#); + println!("This example requires the 'serde' feature to run."); println!("Try: cargo run --features serde --example serde"); } diff --git a/examples/strings.rs b/examples/strings.rs index dc5f76b3..2ea97511 100644 --- a/examples/strings.rs +++ b/examples/strings.rs @@ -33,12 +33,12 @@ fn main() -> Result<(), Box> { .register_fn("trim", trim_string) .register_fn("len", count_string_bytes) .register_fn("index_of", find_substring) - .register_fn("display", |label: &str, x: INT| { - // Register string functions using closures - println!("{}: {}", label, x) + // Register string functions using closures + .register_fn("display", |label: &str, value: INT| { + println!("{}: {}", label, value) }) - .register_fn("display", |label: ImmutableString, x: &str| { - println!(r#"{}: "{}""#, label, x) // Quote the input string + .register_fn("display", |label: ImmutableString, value: &str| { + println!(r#"{}: "{}""#, label, value) // Quote the input string }); let mut scope = Scope::new(); diff --git a/examples/threading.rs b/examples/threading.rs index 527b9214..f28da439 100644 --- a/examples/threading.rs +++ b/examples/threading.rs @@ -1,5 +1,8 @@ use rhai::{Engine, RegisterFn, INT}; +#[cfg(feature = "sync")] +use std::sync::Mutex; + fn main() { // Channel: Script -> Master let (tx_script, rx_master) = std::sync::mpsc::channel(); @@ -7,10 +10,7 @@ fn main() { let (tx_master, rx_script) = std::sync::mpsc::channel(); #[cfg(feature = "sync")] - let (tx_script, rx_script) = ( - std::sync::Mutex::new(tx_script), - std::sync::Mutex::new(rx_script), - ); + let (tx_script, rx_script) = (Mutex::new(tx_script), Mutex::new(rx_script)); // Spawn thread with Engine std::thread::spawn(move || { @@ -22,7 +22,7 @@ fn main() { #[cfg(not(feature = "sync"))] engine - .register_fn("get", move || rx_script.recv().unwrap()) + .register_fn("get", move || rx_script.recv().unwrap_or_default()) .register_fn("put", move |v: INT| tx_script.send(v).unwrap()); #[cfg(feature = "sync")] From fc7697d504c00a5f74837c9edd174e933f4ec9e3 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 21 Feb 2021 13:51:24 +0800 Subject: [PATCH 4/8] Reflect visibility to generated modules. --- codegen/src/function.rs | 17 +++++++++-------- codegen/src/module.rs | 5 +++-- codegen/src/test/function.rs | 14 +++++++------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index d3a7f792..bbed092d 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -16,6 +16,7 @@ use quote::{quote, quote_spanned, ToTokens}; use syn::{ parse::{Parse, ParseStream, Parser}, spanned::Spanned, + VisPublic, Visibility, }; use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; @@ -273,7 +274,7 @@ impl ExportedParams for ExportedFnParams { pub(crate) struct ExportedFn { entire_span: proc_macro2::Span, signature: syn::Signature, - is_public: bool, + visibility: syn::Visibility, pass_context: bool, return_dynamic: bool, mut_receiver: bool, @@ -298,8 +299,7 @@ impl Parse for ExportedFn { // #[cfg] attributes are not allowed on functions due to what is generated for them crate::attrs::deny_cfg_attr(&fn_all.attrs)?; - // Determine if the function is public. - let is_public = matches!(fn_all.vis, syn::Visibility::Public(_)); + let visibility = fn_all.vis; // Determine if the function requires a call context if let Some(first_arg) = fn_all.sig.inputs.first() { @@ -408,7 +408,7 @@ impl Parse for ExportedFn { Ok(ExportedFn { entire_span, signature: fn_all.sig, - is_public, + visibility, pass_context, return_dynamic, mut_receiver, @@ -425,7 +425,7 @@ impl ExportedFn { pub(crate) fn update_scope(&mut self, parent_scope: &ExportScope) { let keep = match (self.params.skip, parent_scope) { (true, _) => false, - (_, ExportScope::PubOnly) => self.is_public, + (_, ExportScope::PubOnly) => self.is_public(), (_, ExportScope::Prefix(s)) => self.name().to_string().starts_with(s), (_, ExportScope::All) => true, }; @@ -449,7 +449,7 @@ impl ExportedFn { } pub(crate) fn is_public(&self) -> bool { - self.is_public + !matches!(self.visibility, syn::Visibility::Inherited) } pub(crate) fn span(&self) -> &proc_macro2::Span { @@ -593,9 +593,10 @@ impl ExportedFn { let input_types_block = self.generate_input_types("Token"); let return_type_block = self.generate_return_type("Token"); let dyn_result_fn_block = self.generate_dynamic_fn(); + let vis = self.visibility; quote! { - #[allow(unused)] - pub mod #name { + #[automatically_derived] + #vis mod #name { use super::*; struct Token(); #impl_block diff --git a/codegen/src/module.rs b/codegen/src/module.rs index fa9526ec..89b9bc11 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -257,6 +257,7 @@ impl Module { params, .. } = self; + let mod_vis = mod_all.vis; let mod_name = mod_all.ident.clone(); let (_, orig_content) = mod_all.content.take().unwrap(); let mod_attrs = mem::take(&mut mod_all.attrs); @@ -282,7 +283,7 @@ impl Module { // Regenerate the module with the new content added. Ok(quote! { #(#mod_attrs)* - pub mod #mod_name { + #mod_vis mod #mod_name { #(#orig_content)* #(#inner_modules)* #mod_gen @@ -292,7 +293,7 @@ impl Module { // Regenerate the original module as-is. Ok(quote! { #(#mod_attrs)* - pub mod #mod_name { + #mod_vis mod #mod_name { #(#orig_content)* } }) diff --git a/codegen/src/test/function.rs b/codegen/src/test/function.rs index 34e2d38c..238b89c2 100644 --- a/codegen/src/test/function.rs +++ b/codegen/src/test/function.rs @@ -272,7 +272,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_do_nothing { use super::*; struct Token(); @@ -325,7 +325,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_do_something { use super::*; struct Token(); @@ -379,7 +379,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_do_something { use super::*; struct Token(); @@ -436,7 +436,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_return_dynamic { use super::*; struct Token(); @@ -523,7 +523,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_add_together { use super::*; struct Token(); @@ -579,7 +579,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_increment { use super::*; struct Token(); @@ -641,7 +641,7 @@ mod generate_tests { }; let expected_tokens = quote! { - #[allow(unused)] + #[automatically_derived] pub mod rhai_fn_special_print { use super::*; struct Token(); From dd3b16403fc11229e85d8933d8152ead18e0fb41 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 21 Feb 2021 14:11:19 +0800 Subject: [PATCH 5/8] Code cleanup. --- codegen/src/attrs.rs | 6 +- codegen/src/function.rs | 132 +++++++++++++++++------------------ codegen/src/module.rs | 4 +- codegen/src/register.rs | 2 +- codegen/src/rhai_module.rs | 6 +- codegen/src/test/function.rs | 7 ++ 6 files changed, 79 insertions(+), 78 deletions(-) diff --git a/codegen/src/attrs.rs b/codegen/src/attrs.rs index bd2272a4..48578518 100644 --- a/codegen/src/attrs.rs +++ b/codegen/src/attrs.rs @@ -101,7 +101,7 @@ pub fn parse_punctuated_items( }) } -pub(crate) fn outer_item_attributes( +pub fn outer_item_attributes( args: proc_macro2::TokenStream, _attr_name: &str, ) -> syn::Result { @@ -116,7 +116,7 @@ pub(crate) fn outer_item_attributes( T::from_info(export_info) } -pub(crate) fn inner_item_attributes( +pub fn inner_item_attributes( attrs: &mut Vec, attr_name: &str, ) -> syn::Result { @@ -132,7 +132,7 @@ pub(crate) fn inner_item_attributes( } } -pub(crate) fn deny_cfg_attr(attrs: &Vec) -> syn::Result<()> { +pub fn deny_cfg_attr(attrs: &Vec) -> syn::Result<()> { if let Some(cfg_attr) = attrs .iter() .find(|a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index bbed092d..abf398b2 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -1,10 +1,3 @@ -#![allow(unused)] - -#[cfg(no_std)] -use core::mem; -#[cfg(not(no_std))] -use std::mem; - #[cfg(no_std)] use alloc::format; #[cfg(not(no_std))] @@ -14,9 +7,8 @@ use std::borrow::Cow; use quote::{quote, quote_spanned, ToTokens}; use syn::{ - parse::{Parse, ParseStream, Parser}, + parse::{Parse, ParseStream}, spanned::Spanned, - VisPublic, Visibility, }; use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; @@ -83,7 +75,7 @@ impl FnSpecialAccess { } } -pub(crate) fn flatten_type_groups(ty: &syn::Type) -> &syn::Type { +pub fn flatten_type_groups(ty: &syn::Type) -> &syn::Type { match ty { syn::Type::Group(syn::TypeGroup { ref elem, .. }) | syn::Type::Paren(syn::TypeParen { ref elem, .. }) => flatten_type_groups(elem.as_ref()), @@ -91,7 +83,7 @@ pub(crate) fn flatten_type_groups(ty: &syn::Type) -> &syn::Type { } } -pub(crate) fn print_type(ty: &syn::Type) -> String { +pub fn print_type(ty: &syn::Type) -> String { ty.to_token_stream() .to_string() .replace(" , ", ", ") @@ -104,7 +96,7 @@ pub(crate) fn print_type(ty: &syn::Type) -> String { } #[derive(Debug, Default)] -pub(crate) struct ExportedFnParams { +pub struct ExportedFnParams { pub name: Vec, pub return_raw: bool, pub pure: bool, @@ -191,53 +183,20 @@ impl ExportedParams for ExportedFnParams { )) } ("name", Some(s)) => name.push(s.value()), - ("set", Some(s)) => { - special = match special { - FnSpecialAccess::None => FnSpecialAccess::Property(Property::Set( - syn::Ident::new(&s.value(), s.span()), - )), - _ => return Err(syn::Error::new(item_span.span(), "conflicting setter")), - } - } - ("get", Some(s)) => { - special = match special { - FnSpecialAccess::None => FnSpecialAccess::Property(Property::Get( - syn::Ident::new(&s.value(), s.span()), - )), - _ => return Err(syn::Error::new(item_span.span(), "conflicting getter")), - } - } - ("index_get", None) => { - special = match special { - FnSpecialAccess::None => FnSpecialAccess::Index(Index::Get), - _ => { - return Err(syn::Error::new(item_span.span(), "conflicting index_get")) - } - } + + ("index_get", Some(s)) + | ("index_set", Some(s)) + | ("return_raw", Some(s)) + | ("pure", Some(s)) + | ("skip", Some(s)) + | ("global", Some(s)) + | ("internal", Some(s)) => { + return Err(syn::Error::new(s.span(), "extraneous value")) } - ("index_set", None) => { - special = match special { - FnSpecialAccess::None => FnSpecialAccess::Index(Index::Set), - _ => { - return Err(syn::Error::new(item_span.span(), "conflicting index_set")) - } - } - } - ("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => { - return Err(syn::Error::new(s.span(), "extraneous value")) - } ("pure", None) => pure = true, - ("pure", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")), ("return_raw", None) => return_raw = true, - ("return_raw", Some(s)) => { - return Err(syn::Error::new(s.span(), "extraneous value")) - } ("skip", None) => skip = true, - ("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")), - ("global", Some(s)) | ("internal", Some(s)) => { - return Err(syn::Error::new(s.span(), "extraneous value")) - } ("global", None) => match namespace { FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Global, FnNamespaceAccess::Global => (), @@ -248,6 +207,40 @@ impl ExportedParams for ExportedFnParams { FnNamespaceAccess::Internal => (), _ => return Err(syn::Error::new(key.span(), "conflicting namespace")), }, + + ("get", Some(s)) => { + special = match special { + FnSpecialAccess::None => FnSpecialAccess::Property(Property::Get( + syn::Ident::new(&s.value(), s.span()), + )), + _ => return Err(syn::Error::new(item_span.span(), "conflicting getter")), + } + } + ("set", Some(s)) => { + special = match special { + FnSpecialAccess::None => FnSpecialAccess::Property(Property::Set( + syn::Ident::new(&s.value(), s.span()), + )), + _ => return Err(syn::Error::new(item_span.span(), "conflicting setter")), + } + } + ("index_get", None) => { + special = match special { + FnSpecialAccess::None => FnSpecialAccess::Index(Index::Get), + _ => { + return Err(syn::Error::new(item_span.span(), "conflicting index_get")) + } + } + } + ("index_set", None) => { + special = match special { + FnSpecialAccess::None => FnSpecialAccess::Index(Index::Set), + _ => { + return Err(syn::Error::new(item_span.span(), "conflicting index_set")) + } + } + } + (attr, _) => { return Err(syn::Error::new( key.span(), @@ -271,7 +264,7 @@ impl ExportedParams for ExportedFnParams { } #[derive(Debug)] -pub(crate) struct ExportedFn { +pub struct ExportedFn { entire_span: proc_macro2::Span, signature: syn::Signature, visibility: syn::Visibility, @@ -418,11 +411,11 @@ impl Parse for ExportedFn { } impl ExportedFn { - pub(crate) fn params(&self) -> &ExportedFnParams { + pub fn params(&self) -> &ExportedFnParams { &self.params } - pub(crate) fn update_scope(&mut self, parent_scope: &ExportScope) { + pub fn update_scope(&mut self, parent_scope: &ExportScope) { let keep = match (self.params.skip, parent_scope) { (true, _) => false, (_, ExportScope::PubOnly) => self.is_public(), @@ -432,35 +425,35 @@ impl ExportedFn { self.params.skip = !keep; } - pub(crate) fn skipped(&self) -> bool { + pub fn skipped(&self) -> bool { self.params.skip } - pub(crate) fn pass_context(&self) -> bool { + pub fn pass_context(&self) -> bool { self.pass_context } - pub(crate) fn signature(&self) -> &syn::Signature { + pub fn signature(&self) -> &syn::Signature { &self.signature } - pub(crate) fn mutable_receiver(&self) -> bool { + pub fn mutable_receiver(&self) -> bool { self.mut_receiver } - pub(crate) fn is_public(&self) -> bool { + pub fn is_public(&self) -> bool { !matches!(self.visibility, syn::Visibility::Inherited) } - pub(crate) fn span(&self) -> &proc_macro2::Span { + pub fn span(&self) -> &proc_macro2::Span { &self.entire_span } - pub(crate) fn name(&self) -> &syn::Ident { + pub fn name(&self) -> &syn::Ident { &self.signature.ident } - pub(crate) fn exported_names(&self) -> Vec { + pub fn exported_names(&self) -> Vec { let mut literals: Vec<_> = self .params .name @@ -482,24 +475,24 @@ impl ExportedFn { literals } - pub(crate) fn exported_name<'n>(&'n self) -> Cow<'n, str> { + pub fn exported_name<'n>(&'n self) -> Cow<'n, str> { self.params.name.last().map_or_else( || self.signature.ident.to_string().into(), |s| s.as_str().into(), ) } - pub(crate) fn arg_list(&self) -> impl Iterator { + pub fn arg_list(&self) -> impl Iterator { let skip = if self.pass_context { 1 } else { 0 }; self.signature.inputs.iter().skip(skip) } - pub(crate) fn arg_count(&self) -> usize { + pub fn arg_count(&self) -> usize { let skip = if self.pass_context { 1 } else { 0 }; self.signature.inputs.len() - skip } - pub(crate) fn return_type(&self) -> Option<&syn::Type> { + pub fn return_type(&self) -> Option<&syn::Type> { if let syn::ReturnType::Type(_, ref ret_type) = self.signature.output { Some(flatten_type_groups(ret_type)) } else { @@ -604,6 +597,7 @@ impl ExportedFn { #input_names_block #input_types_block #return_type_block + #[allow(unused)] #dyn_result_fn_block } } diff --git a/codegen/src/module.rs b/codegen/src/module.rs index 89b9bc11..dc0e8571 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -20,7 +20,7 @@ use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams}; use crate::function::ExportedFnParams; #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] -pub(crate) struct ExportedModParams { +pub struct ExportedModParams { pub name: String, skip: bool, pub scope: ExportScope, @@ -97,7 +97,7 @@ impl ExportedParams for ExportedModParams { } #[derive(Debug)] -pub(crate) struct Module { +pub struct Module { mod_all: syn::ItemMod, fns: Vec, consts: Vec, diff --git a/codegen/src/register.rs b/codegen/src/register.rs index ecd49d1e..8ea91fd3 100644 --- a/codegen/src/register.rs +++ b/codegen/src/register.rs @@ -1,7 +1,7 @@ use quote::{quote, quote_spanned}; use syn::{parse::Parser, spanned::Spanned}; -pub(crate) fn generated_module_path( +pub fn generated_module_path( fn_path: &syn::Path, ) -> syn::punctuated::Punctuated { let mut g = fn_path.clone().segments; diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index cd359d8b..fc4bc82a 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -9,9 +9,9 @@ use crate::function::{ }; use crate::module::Module; -pub(crate) type ExportedConst = (String, Box, syn::Expr); +pub type ExportedConst = (String, Box, syn::Expr); -pub(crate) fn generate_body( +pub fn generate_body( fns: &mut [ExportedFn], consts: &[ExportedConst], sub_modules: &mut [Module], @@ -224,7 +224,7 @@ pub(crate) fn generate_body( } } -pub(crate) fn check_rename_collisions(fns: &Vec) -> Result<(), syn::Error> { +pub fn check_rename_collisions(fns: &Vec) -> Result<(), syn::Error> { fn make_key(name: impl ToString, item_fn: &ExportedFn) -> String { item_fn .arg_list() diff --git a/codegen/src/test/function.rs b/codegen/src/test/function.rs index 238b89c2..58c2613a 100644 --- a/codegen/src/test/function.rs +++ b/codegen/src/test/function.rs @@ -308,6 +308,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn() -> Result > { Ok(Dynamic::from(do_nothing())) } @@ -362,6 +363,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn(x: usize) -> Result > { Ok(Dynamic::from(do_something(x))) } @@ -416,6 +418,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn(context: NativeCallContext, x: usize) -> Result > { Ok(Dynamic::from(do_something(context, x))) } @@ -472,6 +475,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn() -> Result > { Ok(return_dynamic()) } @@ -562,6 +566,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn(x: usize, y: usize) -> Result > { Ok(Dynamic::from(add_together(x, y))) } @@ -623,6 +628,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn(x: &mut usize, y: usize) -> Result > { Ok(Dynamic::from(increment(x, y))) } @@ -678,6 +684,7 @@ mod generate_tests { pub fn token_return_type() -> &'static str { Token().return_type() } + #[allow(unused)] pub fn dynamic_result_fn(message: &str) -> Result > { Ok(Dynamic::from(special_print(message))) } From 4120e3c88e04df2095fadfe6a6f5b8f92d7d713d Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 21 Feb 2021 14:26:31 +0800 Subject: [PATCH 6/8] Include decimal in generated docs. --- Cargo.toml | 2 +- src/dynamic.rs | 4 ++-- src/module/mod.rs | 4 ++-- src/packages/arithmetic.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fe3dffdc..57743468 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,4 +111,4 @@ instant= { version = "0.1" } # WASM implementation of std::time::Instant instant= { version = "0.1" } # WASM implementation of std::time::Instant [package.metadata.docs.rs] -features = [ "metadata", "internals" ] +features = [ "metadata", "internals", "decimal" ] diff --git a/src/dynamic.rs b/src/dynamic.rs index a220f86f..8e9e9efb 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -1357,10 +1357,10 @@ impl Dynamic { _ => Err(self.type_name()), } } - /// Cast the [`Dynamic`] as a [`Decimal`] and return it. + /// _(DECIMAL)_ Cast the [`Dynamic`] as a [`Decimal`] and return it. /// Returns the name of the actual type if the cast fails. /// - /// Available only under `decimal`. + /// Exported under the `decimal` feature only. #[cfg(feature = "decimal")] #[inline(always)] pub fn as_decimal(self) -> Result { diff --git a/src/module/mod.rs b/src/module/mod.rs index 0aba0ce7..2c3f1e51 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1738,7 +1738,8 @@ impl Module { ) } - /// Get an iterator over all script-defined functions in the [`Module`]. + /// _(INTERNALS)_ Get an iterator over all script-defined functions in the [`Module`]. + /// Exported under the `internals` feature only. /// /// Function metadata includes: /// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]). @@ -1746,7 +1747,6 @@ impl Module { /// 3) Function name (as string slice). /// 4) Number of parameters. /// 5) _(INTERNALS)_ Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef]. - /// Exported under the `internals` feature only. #[cfg(not(feature = "no_function"))] #[cfg(feature = "internals")] #[inline(always)] diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 817be5b5..0c96a6af 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -437,7 +437,7 @@ mod f64_functions { #[cfg(feature = "decimal")] #[export_module] -mod decimal_functions { +pub mod decimal_functions { use rust_decimal::{prelude::Zero, Decimal}; #[rhai_fn(skip, return_raw)] From 0b49865f297b4299f832cb9ad31e0ebb88232261 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 21 Feb 2021 14:41:20 +0800 Subject: [PATCH 7/8] Fix no_std build. --- src/fn_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 13ee3102..2bede593 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -366,7 +366,7 @@ impl Engine { ) -> Result> { #[inline(always)] fn make_error( - name: String, + name: crate::stdlib::string::String, fn_def: &crate::ast::ScriptFnDef, state: &State, err: Box, From 067983bb5758d1b2caec4821bbbe640e07485e59 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 21 Feb 2021 15:44:01 +0800 Subject: [PATCH 8/8] Fix codegen tests. --- codegen/src/function.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index abf398b2..8738b410 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -411,6 +411,8 @@ impl Parse for ExportedFn { } impl ExportedFn { + #![allow(unused)] + pub fn params(&self) -> &ExportedFnParams { &self.params } @@ -708,13 +710,6 @@ impl ExportedFn { pub fn generate_impl(&self, on_type_name: &str) -> proc_macro2::TokenStream { let sig_name = self.name().clone(); - let name = self - .params - .name - .last() - .cloned() - .unwrap_or_else(|| self.name().to_string()); - let arg_count = self.arg_count(); let is_method_call = self.mutable_receiver();