diff --git a/src/api/compile.rs b/src/api/compile.rs index 882d047a..a23efc11 100644 --- a/src/api/compile.rs +++ b/src/api/compile.rs @@ -1,7 +1,7 @@ //! Module that defines the public compilation API of [`Engine`]. use crate::parser::{ParseResult, ParseState}; -use crate::{Engine, RhaiResultOf, Scope, AST}; +use crate::{Engine, Scope, AST}; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -84,7 +84,7 @@ impl Engine { &self, scope: &Scope, script: impl AsRef, - ) -> RhaiResultOf { + ) -> crate::RhaiResultOf { use crate::{ ast::{ASTNode, Expr, Stmt}, func::native::shared_take_or_clone, @@ -351,14 +351,18 @@ impl Engine { /// ``` #[cfg(not(feature = "no_object"))] #[inline(always)] - pub fn parse_json(&self, json: impl AsRef, has_null: bool) -> RhaiResultOf { + pub fn parse_json( + &self, + json: impl AsRef, + has_null: bool, + ) -> crate::RhaiResultOf { use crate::tokenizer::Token; fn parse_json_inner( engine: &Engine, json: &str, has_null: bool, - ) -> RhaiResultOf { + ) -> crate::RhaiResultOf { let mut scope = Scope::new(); let json_text = json.trim_start(); let scripts = if json_text.starts_with(Token::MapStart.literal_syntax()) { diff --git a/src/engine.rs b/src/engine.rs index 121101fb..eb0a1f8f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -10,8 +10,8 @@ use crate::r#unsafe::unsafe_cast_var_name_to_lifetime; use crate::tokenizer::Token; use crate::types::dynamic::{map_std_type_name, AccessMode, Union, Variant}; use crate::{ - calc_fn_params_hash, combine_hashes, Dynamic, FnArgsVec, Identifier, ImmutableString, Module, - Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, StaticVec, ERR, INT, + Dynamic, Identifier, ImmutableString, Module, Position, RhaiError, RhaiResult, RhaiResultOf, + Scope, Shared, StaticVec, ERR, INT, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -399,9 +399,9 @@ impl ChainArgument { #[inline(always)] #[cfg(not(feature = "no_object"))] #[must_use] - pub fn into_fn_call_args(self) -> (FnArgsVec, Position) { + pub fn into_fn_call_args(self) -> (crate::FnArgsVec, Position) { match self { - Self::MethodCallArgs(None, pos) => (FnArgsVec::new_const(), pos), + Self::MethodCallArgs(None, pos) => (crate::FnArgsVec::new_const(), pos), Self::MethodCallArgs(Some(mut values), pos) => { (values.iter_mut().map(std::mem::take).collect(), pos) } @@ -426,7 +426,7 @@ impl ChainArgument { #[inline(always)] #[cfg(not(feature = "no_object"))] #[must_use] - pub fn from_fn_call_args(values: FnArgsVec, pos: Position) -> Self { + pub fn from_fn_call_args(values: crate::FnArgsVec, pos: Position) -> Self { if values.is_empty() { Self::MethodCallArgs(None, pos) } else { @@ -435,6 +435,7 @@ impl ChainArgument { } /// Create an [`IndexValue`][ChainArgument::IndexValue]. #[inline(always)] + #[cfg(not(feature = "no_index"))] #[must_use] pub const fn from_index_value(value: Dynamic, pos: Position) -> Self { Self::IndexValue(value, pos) @@ -1865,7 +1866,7 @@ impl Engine { } = x.as_ref(); let (values, pos) = args.iter().try_fold( - (FnArgsVec::with_capacity(args.len()), Position::NONE), + (crate::FnArgsVec::with_capacity(args.len()), Position::NONE), |(mut values, mut pos), expr| -> RhaiResultOf<_> { let (value, arg_pos) = self.get_arg_value( scope, mods, state, lib, this_ptr, level, expr, constants, @@ -1911,7 +1912,7 @@ impl Engine { } = x.as_ref(); let (values, pos) = args.iter().try_fold( - (FnArgsVec::with_capacity(args.len()), Position::NONE), + (crate::FnArgsVec::with_capacity(args.len()), Position::NONE), |(mut values, mut pos), expr| -> RhaiResultOf<_> { let (value, arg_pos) = self.get_arg_value( scope, mods, state, lib, this_ptr, level, expr, constants, @@ -3246,18 +3247,6 @@ impl Engine { .map_err(|err| err.fill_position(stmt.position())) } - // Has a system function a Rust-native override? - pub(crate) fn has_native_fn_override(&self, hash_script: u64, arg_types: &[TypeId]) -> bool { - let hash_params = calc_fn_params_hash(arg_types.iter().cloned()); - let hash = combine_hashes(hash_script, hash_params); - - // First check the global namespace and packages, but skip modules that are standard because - // they should never conflict with system functions. - self.global_modules.iter().filter(|m| !m.standard).any(|m| m.contains_fn(hash)) - // Then check sub-modules - || self.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash)) - } - /// Check a result to ensure that the data size is within allowable limit. fn check_return_value(&self, mut result: RhaiResult) -> RhaiResult { if let Ok(ref mut r) = result { diff --git a/src/optimizer.rs b/src/optimizer.rs index 2ad5bc47..6f58e2ae 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -9,10 +9,14 @@ use crate::func::builtin::get_builtin_binary_op_fn; use crate::func::hashing::get_hasher; use crate::tokenizer::Token; use crate::types::dynamic::AccessMode; -use crate::{calc_fn_hash, Dynamic, Engine, FnPtr, Position, Scope, StaticVec, AST, INT}; +use crate::{ + calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Position, Scope, + StaticVec, AST, INT, +}; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ + any::TypeId, convert::TryFrom, hash::{Hash, Hasher}, mem, @@ -152,6 +156,18 @@ impl<'a> OptimizerState<'a> { } } +// Has a system function a Rust-native override? +fn has_native_fn_override(engine: &Engine, hash_script: u64, arg_types: &[TypeId]) -> bool { + let hash_params = calc_fn_params_hash(arg_types.iter().cloned()); + let hash = combine_hashes(hash_script, hash_params); + + // First check the global namespace and packages, but skip modules that are standard because + // they should never conflict with system functions. + engine.global_modules.iter().filter(|m| !m.standard).any(|m| m.contains_fn(hash)) + // Then check sub-modules + || engine.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash)) +} + /// Optimize a block of [statements][Stmt]. fn optimize_stmt_block( mut statements: StaticVec, @@ -970,7 +986,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) { return; } // Overloaded operators can override built-in. - _ if x.args.len() == 2 && !state.engine.has_native_fn_override(x.hashes.native, arg_types.as_ref()) => { + _ if x.args.len() == 2 && !has_native_fn_override(state.engine, x.hashes.native, arg_types.as_ref()) => { if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1]) .and_then(|f| { #[cfg(not(feature = "no_function"))] diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index b6c2d894..ecd11b82 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -4,7 +4,7 @@ use crate::plugin::*; use crate::{ def_package, Blob, Dynamic, ExclusiveRange, InclusiveRange, NativeCallContext, Position, - RhaiResultOf, ERR, INT, + RhaiResultOf, INT, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -46,7 +46,9 @@ pub mod blob_functions { // Check if blob will be over max size limit #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_array_size() > 0 && len > _ctx.engine().max_array_size() { - return Err(ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into()); + return Err( + crate::ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into(), + ); } let mut blob = Blob::new(); @@ -117,7 +119,9 @@ pub mod blob_functions { // Check if blob will be over max size limit #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_array_size() > 0 && (len as usize) > _ctx.engine().max_array_size() { - return Err(ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into()); + return Err( + crate::ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into(), + ); } if len as usize > blob.len() { diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index ce1c3345..cd5579ef 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -1,6 +1,6 @@ use crate::plugin::*; use crate::types::dynamic::Variant; -use crate::{def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, ERR, INT}; +use crate::{def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, INT}; use std::iter::{ExactSizeIterator, FusedIterator}; use std::ops::{Range, RangeInclusive}; #[cfg(feature = "no_std")] @@ -26,15 +26,15 @@ where #[cfg(not(feature = "unchecked"))] if let Some(r) = from.checked_add(&step) { if r == from { - return Err(ERR::ErrorInFunctionCall( + return Err(crate::ERR::ErrorInFunctionCall( "range".to_string(), String::new(), - ERR::ErrorArithmetic( + crate::ERR::ErrorArithmetic( "step value cannot be zero".to_string(), - crate::Position::NONE, + Position::NONE, ) .into(), - crate::Position::NONE, + Position::NONE, ) .into()); } @@ -123,18 +123,18 @@ impl BitRange { #[cfg(not(feature = "unchecked"))] if offset >= BITS { - return Err(ERR::ErrorBitFieldBounds(BITS, from, crate::Position::NONE).into()); + return Err(crate::ERR::ErrorBitFieldBounds(BITS, from, Position::NONE).into()); } offset } else { #[cfg(not(feature = "unchecked"))] if let Some(abs_from) = from.checked_abs() { if (abs_from as usize) > BITS { - return Err(ERR::ErrorBitFieldBounds(BITS, from, crate::Position::NONE).into()); + return Err(crate::ERR::ErrorBitFieldBounds(BITS, from, Position::NONE).into()); } BITS - (abs_from as usize) } else { - return Err(ERR::ErrorBitFieldBounds(BITS, from, crate::Position::NONE).into()); + return Err(crate::ERR::ErrorBitFieldBounds(BITS, from, Position::NONE).into()); } #[cfg(feature = "unchecked")] @@ -328,9 +328,9 @@ def_package! { pub fn new(from: FLOAT, to: FLOAT, step: FLOAT) -> RhaiResultOf { #[cfg(not(feature = "unchecked"))] if step == 0.0 { - return Err(ERR::ErrorInFunctionCall("range".to_string(), "".to_string(), - ERR::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE).into(), - crate::Position::NONE, + return Err(crate::ERR::ErrorInFunctionCall("range".to_string(), "".to_string(), + crate::ERR::ErrorArithmetic("step value cannot be zero".to_string(), Position::NONE).into(), + Position::NONE, ).into()); } @@ -390,9 +390,9 @@ def_package! { pub fn new(from: Decimal, to: Decimal, step: Decimal) -> RhaiResultOf { #[cfg(not(feature = "unchecked"))] if step.is_zero() { - return Err(ERR::ErrorInFunctionCall("range".to_string(), "".to_string(), - ERR::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE).into(), - crate::Position::NONE, + return Err(crate::ERR::ErrorInFunctionCall("range".to_string(), "".to_string(), + crate::ERR::ErrorArithmetic("step value cannot be zero".to_string(), Position::NONE).into(), + Position::NONE, ).into()); } diff --git a/src/parser.rs b/src/parser.rs index a29c65d9..e302a150 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -182,6 +182,7 @@ impl<'e> ParseState<'e> { /// Get an interned string, creating one if it is not yet interned. #[inline(always)] + #[allow(dead_code)] #[must_use] pub fn get_interned_string( &mut self, diff --git a/src/types/interner.rs b/src/types/interner.rs index df3c4af7..db9c2745 100644 --- a/src/types/interner.rs +++ b/src/types/interner.rs @@ -1,8 +1,9 @@ +#[cfg(not(feature = "no_object"))] use crate::engine::{make_getter, make_setter, FN_GET, FN_SET}; use crate::{Identifier, ImmutableString}; +use std::ops::AddAssign; #[cfg(feature = "no_std")] use std::prelude::v1::*; -use std::{collections::BTreeMap, ops::AddAssign}; /// _(internals)_ A factory of identifiers from text strings. /// Exported under the `internals` feature only. @@ -14,9 +15,11 @@ use std::{collections::BTreeMap, ops::AddAssign}; #[derive(Debug, Clone, Default, Hash)] pub struct StringsInterner { /// Property getters. - getters: BTreeMap, + #[cfg(not(feature = "no_object"))] + getters: std::collections::BTreeMap, /// Property setters. - setters: BTreeMap, + #[cfg(not(feature = "no_object"))] + setters: std::collections::BTreeMap, } impl StringsInterner { @@ -25,8 +28,10 @@ impl StringsInterner { #[must_use] pub fn new() -> Self { Self { - getters: BTreeMap::new(), - setters: BTreeMap::new(), + #[cfg(not(feature = "no_object"))] + getters: std::collections::BTreeMap::new(), + #[cfg(not(feature = "no_object"))] + setters: std::collections::BTreeMap::new(), } } /// Get an identifier from a text string and prefix, adding it to the interner if necessary. @@ -41,20 +46,29 @@ impl StringsInterner { prefix: &'static str, text: impl AsRef + Into + Into, ) -> ImmutableString { - let (dict, mapper) = match prefix { - "" => return text.into(), - FN_GET => (&mut self.getters, make_getter as fn(&str) -> String), - FN_SET => (&mut self.setters, make_setter as fn(&str) -> String), - _ => unreachable!("unsupported prefix {}", prefix), - }; + #[cfg(not(feature = "no_object"))] + { + let (dict, mapper) = match prefix { + "" => return text.into(), + FN_GET => (&mut self.getters, make_getter as fn(&str) -> String), + FN_SET => (&mut self.setters, make_setter as fn(&str) -> String), + _ => unreachable!("unsupported prefix {}", prefix), + }; - if dict.contains_key(text.as_ref()) { - self.getters.get(text.as_ref()).expect("exists").clone() - } else { - let value: ImmutableString = mapper(text.as_ref()).into(); - let text = text.into(); - dict.insert(text, value.clone()); - value + if dict.contains_key(text.as_ref()) { + self.getters.get(text.as_ref()).expect("exists").clone() + } else { + let value: ImmutableString = mapper(text.as_ref()).into(); + let text = text.into(); + dict.insert(text, value.clone()); + value + } + } + + #[cfg(feature = "no_object")] + match prefix { + "" => return text.into(), + _ => unreachable!("unsupported prefix {}", prefix), } } /// Merge another [`IdentifierBuilder`] into this. @@ -65,7 +79,12 @@ impl StringsInterner { impl AddAssign for StringsInterner { #[inline(always)] fn add_assign(&mut self, rhs: Self) { - self.getters.extend(rhs.getters.into_iter()); - self.setters.extend(rhs.setters.into_iter()); + let _rhs = rhs; + + #[cfg(not(feature = "no_object"))] + { + self.getters.extend(_rhs.getters.into_iter()); + self.setters.extend(_rhs.setters.into_iter()); + } } }