From 958762079e8838f25310e66d43704cb06410e44c Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 10 Nov 2020 23:26:50 +0800 Subject: [PATCH] Change modules to namespace. --- RELEASES.md | 4 +-- doc/src/language/fn-namespaces.md | 8 ++--- doc/src/rust/modules/create.md | 4 +-- src/ast.rs | 16 ++++----- src/engine.rs | 58 ++++++++++++++---------------- src/engine_api.rs | 7 ++-- src/engine_settings.rs | 32 ++++++++--------- src/fn_call.rs | 60 +++++++++++++++---------------- src/lib.rs | 10 +++--- src/module/mod.rs | 28 +++++++-------- src/optimize.rs | 6 ++-- src/parser.rs | 36 +++++++++---------- src/token.rs | 2 +- src/utils.rs | 8 ++--- 14 files changed, 137 insertions(+), 142 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 1e200e97..48ef1e69 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -209,7 +209,7 @@ Bug fixes --------- * Fixes bug that prevents calling functions in closures. -* Fixes bug that erroneously consumes the first argument to a module-qualified function call. +* Fixes bug that erroneously consumes the first argument to a namespace-qualified function call. New features ------------ @@ -299,7 +299,7 @@ New features * The boolean `^` (XOR) operator is added. * `FnPtr` is exposed as the function pointer type. * `rhai::module_resolvers::ModuleResolversCollection` added to try a list of module resolvers. -* It is now possible to mutate the first argument of a module-qualified function call when the argument is a simple variable (but not a module constant). +* It is now possible to mutate the first argument of a namespace-qualified function call when the argument is a simple variable (but not a module constant). * Many configuration/setting API's now returns `&mut Self` so that the calls can be chained. * `String` parameters in functions are supported (but inefficiently). diff --git a/doc/src/language/fn-namespaces.md b/doc/src/language/fn-namespaces.md index 0d798ae4..ba551367 100644 --- a/doc/src/language/fn-namespaces.md +++ b/doc/src/language/fn-namespaces.md @@ -15,10 +15,10 @@ allow combining all functions in one [`AST`] into another, forming a new, unifie In general, there are two types of _namespaces_ where functions are looked up: -| Namespace | Source | Lookup method | Sub-modules? | Variables? | -| --------- | ------------------------------------------------------------------------------------- | ------------------------------ | :----------: | :--------: | -| Global | 1) `Engine::register_XXX` API
2) [`AST`] being evaluated
3) [packages] loaded | simple function name | ignored | ignored | -| Module | [`Module`] | module-qualified function name | yes | yes | +| Namespace | Source | Lookup method | Sub-modules? | Variables? | +| --------- | ------------------------------------------------------------------------------------- | --------------------------------- | :----------: | :--------: | +| Global | 1) `Engine::register_XXX` API
2) [`AST`] being evaluated
3) [packages] loaded | simple function name | ignored | ignored | +| Module | [`Module`] | namespace-qualified function name | yes | yes | Global Namespace diff --git a/doc/src/rust/modules/create.md b/doc/src/rust/modules/create.md index 51462b22..069e5896 100644 --- a/doc/src/rust/modules/create.md +++ b/doc/src/rust/modules/create.md @@ -69,9 +69,9 @@ resolver.insert("question", module); let mut engine = Engine::new(); engine.set_module_resolver(Some(resolver)); -// Use module-qualified variables +// Use namespace-qualified variables engine.eval::(r#"import "question" as q; q::answer + 1"#)? == 42; -// Call module-qualified functions +// Call namespace-qualified functions engine.eval::(r#"import "question" as q; q::inc(q::answer)"#)? == 42; ``` diff --git a/src/ast.rs b/src/ast.rs index e5409b24..d99e6a74 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -2,7 +2,7 @@ use crate::dynamic::{Dynamic, Union}; use crate::fn_native::{FnPtr, Shared}; -use crate::module::{Module, ModuleRef}; +use crate::module::{Module, NamespaceRef}; use crate::syntax::FnCustomSyntaxEval; use crate::token::{Position, Token, NO_POS}; use crate::utils::ImmutableString; @@ -778,7 +778,7 @@ impl Stmt { } } -/// _[INTERNALS]_ A type wrapping a custom syntax definition. +/// _[INTERNALS]_ A custom syntax definition. /// Exported under the `internals` feature only. /// /// ## WARNING @@ -823,7 +823,7 @@ impl CustomExpr { /// Exported under the `internals` feature only. /// /// This type is mainly used to provide a standard `Hash` implementation -/// to floating-point numbers, allowing `Expr` to derive `Hash` automatically. +/// for floating-point numbers, allowing `Expr` to derive `Hash`. /// /// ## WARNING /// @@ -856,7 +856,7 @@ impl From for FloatWrapper { } } -/// A binary expression structure. +/// _[INTERNALS]_ A binary expression. /// Exported under the `internals` feature only. /// /// ## WARNING @@ -877,7 +877,7 @@ pub struct BinaryExpr { /// /// This type is volatile and may change. #[derive(Debug, Clone, Hash, Default)] -pub struct FnCallInfo { +pub struct FnCallExpr { /// Pre-calculated hash for a script-defined function of the same name and number of parameters. pub hash: u64, /// Call native functions only? Set to `true` to skip searching for script-defined function overrides @@ -889,7 +889,7 @@ pub struct FnCallInfo { /// Type is `bool` in order for `FnCallInfo` to be `Hash` pub def_value: Option, /// Namespace of the function, if any. Boxed because it occurs rarely. - pub namespace: Option>, + pub namespace: Option>, /// Function name. /// Use `Cow<'static, str>` because a lot of operators (e.g. `==`, `>=`) are implemented as function calls /// and the function names are predictable, so no need to allocate a new `String`. @@ -918,7 +918,7 @@ pub enum Expr { /// FnPtr constant. FnPointer(Box), /// Variable access - (optional index, optional modules, hash, variable name) - Variable(Box<(Option, Option>, u64, Ident)>), + Variable(Box<(Option, Option>, u64, Ident)>), /// Property access - (getter, setter), prop Property(Box<((String, String), IdentX)>), /// { stmt } @@ -926,7 +926,7 @@ pub enum Expr { /// Wrapped expression - should not be optimized away. Expr(Box), /// func(expr, ... ) - FnCall(Box, Position), + FnCall(Box, Position), /// lhs.rhs Dot(Box, Position), /// expr[expr] diff --git a/src/engine.rs b/src/engine.rs index 57ced10c..b2b4480f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,10 +1,10 @@ //! Main module defining the script evaluation `Engine`. -use crate::ast::{BinaryExpr, Expr, FnCallInfo, Ident, IdentX, ReturnType, Stmt}; +use crate::ast::{BinaryExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, Stmt}; use crate::dynamic::{map_std_type_name, Dynamic, Union, Variant}; use crate::fn_call::run_builtin_op_assignment; use crate::fn_native::{Callback, FnPtr, OnVarCallback, Shared}; -use crate::module::{Module, ModuleRef}; +use crate::module::{Module, NamespaceRef}; use crate::optimize::OptimizationLevel; use crate::packages::{Package, PackagesCollection, StandardPackage}; use crate::r#unsafe::unsafe_cast_var_name_to_lifetime; @@ -593,7 +593,7 @@ pub struct Engine { /// Max limits. #[cfg(not(feature = "unchecked"))] - pub(crate) limits_set: Limits, + pub(crate) limits: Limits, } impl fmt::Debug for Engine { @@ -636,6 +636,7 @@ pub fn is_anonymous_fn(fn_name: &str) -> bool { } /// Print/debug to stdout +#[inline(always)] fn default_print(_s: &str) { #[cfg(not(feature = "no_std"))] #[cfg(not(target_arch = "wasm32"))] @@ -647,15 +648,15 @@ fn default_print(_s: &str) { pub fn search_imports( mods: &Imports, state: &mut State, - modules: &ModuleRef, + namespace: &NamespaceRef, ) -> Result, Box> { - let Ident { name: root, pos } = &modules[0]; + let Ident { name: root, pos } = &namespace[0]; // Qualified - check if the root module is directly indexed let index = if state.always_search { 0 } else { - modules.index().map_or(0, NonZeroUsize::get) + namespace.index().map_or(0, NonZeroUsize::get) }; Ok(if index > 0 { @@ -670,7 +671,7 @@ pub fn search_imports( impl Engine { /// Create a new `Engine` - #[inline(always)] + #[inline] pub fn new() -> Self { // Create the new scripting Engine let mut engine = Self { @@ -710,7 +711,7 @@ impl Engine { }, #[cfg(not(feature = "unchecked"))] - limits_set: Limits { + limits: Limits { max_call_stack_depth: MAX_CALL_STACK_DEPTH, max_expr_depth: MAX_EXPR_DEPTH, #[cfg(not(feature = "no_function"))] @@ -733,7 +734,7 @@ impl Engine { /// Create a new `Engine` with minimal built-in functions. /// Use the `load_package` method to load additional packages of functions. - #[inline(always)] + #[inline] pub fn new_raw() -> Self { Self { id: Default::default(), @@ -762,7 +763,7 @@ impl Engine { }, #[cfg(not(feature = "unchecked"))] - limits_set: Limits { + limits: Limits { max_call_stack_depth: MAX_CALL_STACK_DEPTH, max_expr_depth: MAX_EXPR_DEPTH, #[cfg(not(feature = "no_function"))] @@ -780,7 +781,7 @@ impl Engine { } /// Search for a variable within the scope or within imports, - /// depending on whether the variable name is qualified. + /// depending on whether the variable name is namespace-qualified. pub(crate) fn search_namespace<'s, 'a>( &self, scope: &'s mut Scope, @@ -1000,7 +1001,7 @@ impl Engine { match rhs { // xxx.fn_name(arg_expr_list) Expr::FnCall(x, pos) if x.namespace.is_none() => { - let FnCallInfo { + let FnCallExpr { name, native_only: native, hash, @@ -1073,7 +1074,7 @@ impl Engine { } // {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr Expr::FnCall(x, pos) if x.namespace.is_none() => { - let FnCallInfo { + let FnCallExpr { name, native_only: native, hash, @@ -1157,7 +1158,7 @@ impl Engine { } // xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr Expr::FnCall(f, pos) if f.namespace.is_none() => { - let FnCallInfo { + let FnCallExpr { name, native_only: native, hash, @@ -1209,14 +1210,7 @@ impl Engine { level: usize, new_val: Option<(Dynamic, Position)>, ) -> Result> { - let ( - BinaryExpr { - lhs: dot_lhs, - rhs: dot_rhs, - }, - chain_type, - op_pos, - ) = match expr { + let (BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr { Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos), Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos), _ => unreachable!(), @@ -1230,14 +1224,14 @@ impl Engine { state, lib, this_ptr, - dot_rhs, + rhs, chain_type, &mut idx_values, 0, level, )?; - match dot_lhs { + match lhs { // id.??? or id[???] Expr::Variable(x) => { let Ident { @@ -1249,7 +1243,7 @@ impl Engine { .map_err(|err| err.fill_position(*var_pos))?; let (target, _, typ, pos) = - self.search_namespace(scope, mods, state, lib, this_ptr, dot_lhs)?; + self.search_namespace(scope, mods, state, lib, this_ptr, lhs)?; // Constants cannot be modified match typ { @@ -1262,7 +1256,7 @@ impl Engine { let obj_ptr = &mut target.into(); self.eval_dot_index_chain_helper( - mods, state, lib, &mut None, obj_ptr, dot_rhs, idx_values, chain_type, level, + mods, state, lib, &mut None, obj_ptr, rhs, idx_values, chain_type, level, new_val, ) .map(|(v, _)| v) @@ -1275,7 +1269,7 @@ impl Engine { let val = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?; let obj_ptr = &mut val.into(); self.eval_dot_index_chain_helper( - mods, state, lib, this_ptr, obj_ptr, dot_rhs, idx_values, chain_type, level, + mods, state, lib, this_ptr, obj_ptr, rhs, idx_values, chain_type, level, new_val, ) .map(|(v, _)| v) @@ -1605,7 +1599,7 @@ impl Engine { // Normal function call Expr::FnCall(x, pos) if x.namespace.is_none() => { - let FnCallInfo { + let FnCallExpr { name, native_only: native, capture: cap_scope, @@ -1622,9 +1616,9 @@ impl Engine { .map_err(|err| err.fill_position(*pos)) } - // Module-qualified function call + // Namespace-qualified function call Expr::FnCall(x, pos) if x.namespace.is_some() => { - let FnCallInfo { + let FnCallExpr { name, namespace, hash, @@ -1632,9 +1626,9 @@ impl Engine { def_value, .. } = x.as_ref(); - let modules = namespace.as_ref().map(|v| v.as_ref()); + let namespace = namespace.as_ref().map(|v| v.as_ref()); self.make_qualified_function_call( - scope, mods, state, lib, this_ptr, modules, name, args, *def_value, *hash, + scope, mods, state, lib, this_ptr, namespace, name, args, *def_value, *hash, level, ) .map_err(|err| err.fill_position(*pos)) diff --git a/src/engine_api.rs b/src/engine_api.rs index 084c2040..3207fc94 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -1156,10 +1156,9 @@ impl Engine { ) -> Result { let scripts = [script]; let stream = self.lex(&scripts, None); - { - let mut peekable = stream.peekable(); - self.parse_global_expr(&mut peekable, scope, self.optimization_level) - } + + let mut peekable = stream.peekable(); + self.parse_global_expr(&mut peekable, scope, self.optimization_level) } /// Evaluate a script file. diff --git a/src/engine_settings.rs b/src/engine_settings.rs index 987187f1..b6d7cfd9 100644 --- a/src/engine_settings.rs +++ b/src/engine_settings.rs @@ -53,7 +53,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn set_max_call_levels(&mut self, levels: usize) -> &mut Self { - self.limits_set.max_call_stack_depth = levels; + self.limits.max_call_stack_depth = levels; self } @@ -61,7 +61,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn max_call_levels(&self) -> usize { - self.limits_set.max_call_stack_depth + self.limits.max_call_stack_depth } /// Set the maximum number of operations allowed for a script to run to avoid @@ -69,7 +69,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn set_max_operations(&mut self, operations: u64) -> &mut Self { - self.limits_set.max_operations = if operations == u64::MAX { + self.limits.max_operations = if operations == u64::MAX { 0 } else { operations @@ -81,7 +81,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn max_operations(&self) -> u64 { - self.limits_set.max_operations + self.limits.max_operations } /// Set the maximum number of imported modules allowed for a script. @@ -89,7 +89,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] #[inline(always)] pub fn set_max_modules(&mut self, modules: usize) -> &mut Self { - self.limits_set.max_modules = modules; + self.limits.max_modules = modules; self } @@ -98,7 +98,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] #[inline(always)] pub fn max_modules(&self) -> usize { - self.limits_set.max_modules + self.limits.max_modules } /// Set the depth limits for expressions (0 for unlimited). @@ -109,14 +109,14 @@ impl Engine { max_expr_depth: usize, #[cfg(not(feature = "no_function"))] max_function_expr_depth: usize, ) -> &mut Self { - self.limits_set.max_expr_depth = if max_expr_depth == usize::MAX { + self.limits.max_expr_depth = if max_expr_depth == usize::MAX { 0 } else { max_expr_depth }; #[cfg(not(feature = "no_function"))] { - self.limits_set.max_function_expr_depth = if max_function_expr_depth == usize::MAX { + self.limits.max_function_expr_depth = if max_function_expr_depth == usize::MAX { 0 } else { max_function_expr_depth @@ -129,7 +129,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn max_expr_depth(&self) -> usize { - self.limits_set.max_expr_depth + self.limits.max_expr_depth } /// The depth limit for expressions in functions (0 for unlimited). @@ -137,14 +137,14 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[inline(always)] pub fn max_function_expr_depth(&self) -> usize { - self.limits_set.max_function_expr_depth + self.limits.max_function_expr_depth } /// Set the maximum length of strings (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self { - self.limits_set.max_string_size = if max_size == usize::MAX { 0 } else { max_size }; + self.limits.max_string_size = if max_size == usize::MAX { 0 } else { max_size }; self } @@ -152,7 +152,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn max_string_size(&self) -> usize { - self.limits_set.max_string_size + self.limits.max_string_size } /// Set the maximum length of arrays (0 for unlimited). @@ -160,7 +160,7 @@ impl Engine { #[cfg(not(feature = "no_index"))] #[inline(always)] pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self { - self.limits_set.max_array_size = if max_size == usize::MAX { 0 } else { max_size }; + self.limits.max_array_size = if max_size == usize::MAX { 0 } else { max_size }; self } @@ -169,7 +169,7 @@ impl Engine { #[cfg(not(feature = "no_index"))] #[inline(always)] pub fn max_array_size(&self) -> usize { - self.limits_set.max_array_size + self.limits.max_array_size } /// Set the maximum length of object maps (0 for unlimited). @@ -177,7 +177,7 @@ impl Engine { #[cfg(not(feature = "no_object"))] #[inline(always)] pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self { - self.limits_set.max_map_size = if max_size == usize::MAX { 0 } else { max_size }; + self.limits.max_map_size = if max_size == usize::MAX { 0 } else { max_size }; self } @@ -186,7 +186,7 @@ impl Engine { #[cfg(not(feature = "no_object"))] #[inline(always)] pub fn max_map_size(&self) -> usize { - self.limits_set.max_map_size + self.limits.max_map_size } /// Set the module resolution service used by the `Engine`. diff --git a/src/fn_call.rs b/src/fn_call.rs index 3c258f93..cc740594 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -8,7 +8,7 @@ use crate::engine::{ KEYWORD_PRINT, KEYWORD_TYPE_OF, }; use crate::fn_native::{FnCallArgs, FnPtr}; -use crate::module::{Module, ModuleRef}; +use crate::module::{Module, NamespaceRef}; use crate::optimize::OptimizationLevel; use crate::parse_error::ParseErrorType; use crate::result::EvalAltResult; @@ -432,13 +432,13 @@ impl Engine { pub(crate) fn has_override_by_name_and_arguments( &self, lib: &[&Module], - name: &str, + fn_name: &str, arg_types: impl AsRef<[TypeId]>, pub_only: bool, ) -> bool { let arg_types = arg_types.as_ref(); - let hash_fn = calc_native_fn_hash(empty(), name, arg_types.iter().cloned()); - let hash_script = calc_script_fn_hash(empty(), name, arg_types.len()); + let hash_fn = calc_native_fn_hash(empty(), fn_name, arg_types.iter().cloned()); + let hash_script = calc_script_fn_hash(empty(), fn_name, arg_types.len()); self.has_override(lib, hash_fn, hash_script, pub_only) } @@ -694,7 +694,7 @@ impl Engine { mods: &mut Imports, state: &mut State, lib: &[&Module], - name: &str, + fn_name: &str, hash_script: u64, target: &mut Target, mut call_args: StaticVec, @@ -707,9 +707,9 @@ impl Engine { // Get a reference to the mutation target Dynamic let obj = target.as_mut(); - let mut _fn_name = name; + let mut fn_name = fn_name; - let (result, updated) = if _fn_name == KEYWORD_FN_PTR_CALL && obj.is::() { + let (result, updated) = if fn_name == KEYWORD_FN_PTR_CALL && obj.is::() { // FnPtr call let fn_ptr = obj.read_lock::().unwrap(); // Redirect function name @@ -733,7 +733,7 @@ impl Engine { self.exec_fn_call( mods, state, lib, fn_name, hash, args, false, false, pub_only, None, def_val, level, ) - } else if _fn_name == KEYWORD_FN_PTR_CALL + } else if fn_name == KEYWORD_FN_PTR_CALL && call_args.len() > 0 && call_args[0].is::() { @@ -760,7 +760,7 @@ impl Engine { self.exec_fn_call( mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, None, def_val, level, ) - } else if _fn_name == KEYWORD_FN_PTR_CURRY && obj.is::() { + } else if fn_name == KEYWORD_FN_PTR_CURRY && obj.is::() { // Curry call let fn_ptr = obj.read_lock::().unwrap(); Ok(( @@ -779,7 +779,7 @@ impl Engine { } else if { #[cfg(not(feature = "no_closure"))] { - _fn_name == KEYWORD_IS_SHARED && call_args.is_empty() + fn_name == KEYWORD_IS_SHARED && call_args.is_empty() } #[cfg(feature = "no_closure")] false @@ -793,11 +793,11 @@ impl Engine { // Check if it is a map method call in OOP style #[cfg(not(feature = "no_object"))] if let Some(map) = obj.read_lock::() { - if let Some(val) = map.get(_fn_name) { + if let Some(val) = map.get(fn_name) { if let Some(fn_ptr) = val.read_lock::() { // Remap the function name _redirected = fn_ptr.get_fn_name().clone(); - _fn_name = &_redirected; + fn_name = &_redirected; // Add curried arguments fn_ptr .curry() @@ -809,7 +809,7 @@ impl Engine { hash = if native { 0 } else { - calc_script_fn_hash(empty(), _fn_name, call_args.len()) + calc_script_fn_hash(empty(), fn_name, call_args.len()) }; } } @@ -826,8 +826,7 @@ impl Engine { let args = arg_values.as_mut(); self.exec_fn_call( - mods, state, lib, _fn_name, hash, args, is_ref, true, pub_only, None, def_val, - level, + mods, state, lib, fn_name, hash, args, is_ref, true, pub_only, None, def_val, level, ) }?; @@ -848,7 +847,7 @@ impl Engine { state: &mut State, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, - name: &str, + fn_name: &str, args_expr: impl AsRef<[Expr]>, def_val: Option, mut hash_script: u64, @@ -860,8 +859,9 @@ impl Engine { let args_expr = args_expr.as_ref(); // Handle Fn() - if name == KEYWORD_FN_PTR && args_expr.len() == 1 { - let hash_fn = calc_native_fn_hash(empty(), name, once(TypeId::of::())); + if fn_name == KEYWORD_FN_PTR && args_expr.len() == 1 { + let hash_fn = + calc_native_fn_hash(empty(), fn_name, once(TypeId::of::())); if !self.has_override(lib, hash_fn, hash_script, pub_only) { // Fn - only in function call style @@ -878,7 +878,7 @@ impl Engine { } // Handle curry() - if name == KEYWORD_FN_PTR_CURRY && args_expr.len() > 1 { + if fn_name == KEYWORD_FN_PTR_CURRY && args_expr.len() > 1 { let fn_ptr = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?; if !fn_ptr.is::() { @@ -905,7 +905,7 @@ impl Engine { // Handle is_shared() #[cfg(not(feature = "no_closure"))] - if name == KEYWORD_IS_SHARED && args_expr.len() == 1 { + if fn_name == KEYWORD_IS_SHARED && args_expr.len() == 1 { let value = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?; return Ok(value.is_shared().into()); @@ -915,7 +915,7 @@ impl Engine { let redirected; let mut args_expr = args_expr.as_ref(); let mut curry = StaticVec::new(); - let mut name = name; + let mut name = fn_name; if name == KEYWORD_FN_PTR_CALL && args_expr.len() >= 1 @@ -1078,7 +1078,7 @@ impl Engine { .map(|(v, _)| v) } - /// Call a module-qualified function in normal function-call style. + /// Call a namespace-qualified function in normal function-call style. /// Position in `EvalAltResult` is `None` and must be set afterwards. pub(crate) fn make_qualified_function_call( &self, @@ -1087,8 +1087,8 @@ impl Engine { state: &mut State, lib: &[&Module], this_ptr: &mut Option<&mut Dynamic>, - modules: Option<&ModuleRef>, - name: &str, + namespace: Option<&NamespaceRef>, + fn_name: &str, args_expr: impl AsRef<[Expr]>, def_val: Option, hash_script: u64, @@ -1096,7 +1096,7 @@ impl Engine { ) -> Result> { let args_expr = args_expr.as_ref(); - let modules = modules.as_ref().unwrap(); + let namespace = namespace.as_ref().unwrap(); let mut arg_values: StaticVec<_>; let mut first_arg_value = None; let mut args: StaticVec<_>; @@ -1105,7 +1105,7 @@ impl Engine { // No arguments args = Default::default(); } else { - // See if the first argument is a variable (not module-qualified). + // See if the first argument is a variable (not namespace-qualified). // If so, convert to method-call style in order to leverage potential // &mut first argument and avoid cloning the value if args_expr[0].get_variable_access(true).is_some() { @@ -1151,7 +1151,7 @@ impl Engine { } } - let module = search_imports(mods, state, modules)?; + let module = search_imports(mods, state, namespace)?; // First search in script-defined functions (can override built-in) let func = match module.get_qualified_fn(hash_script) { @@ -1159,7 +1159,7 @@ impl Engine { None => { self.inc_operations(state)?; - // Qualified Rust functions are indexed in two steps: + // Namespace-qualified Rust functions are indexed in two steps: // 1) Calculate a hash in a similar manner to script-defined functions, // i.e. qualifiers + function name + number of arguments. // 2) Calculate a second hash with no qualifiers, empty function name, @@ -1210,8 +1210,8 @@ impl Engine { None => EvalAltResult::ErrorFunctionNotFound( format!( "{}{} ({})", - modules, - name, + namespace, + fn_name, args.iter() .map(|a| if a.is::() { "&str | ImmutableString | String" diff --git a/src/lib.rs b/src/lib.rs index e8019d24..9badf96d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,19 +83,20 @@ mod token; mod r#unsafe; mod utils; -/// The system integer type. +/// The system integer type. It is defined as `i64`. /// /// If the `only_i32` feature is enabled, this will be `i32` instead. #[cfg(not(feature = "only_i32"))] pub type INT = i64; /// The system integer type. +/// It is defined as `i32` since the `only_i32` feature is used. /// /// If the `only_i32` feature is not enabled, this will be `i64` instead. #[cfg(feature = "only_i32")] pub type INT = i32; -/// The system floating-point type. +/// The system floating-point type. It is defined as `f64`. /// /// Not available under the `no_float` feature. #[cfg(not(feature = "no_float"))] @@ -103,6 +104,7 @@ pub type INT = i32; pub type FLOAT = f64; /// The system floating-point type. +/// It is defined as `f32` since the `f32_float` feature is used. /// /// Not available under the `no_float` feature. #[cfg(not(feature = "no_float"))] @@ -168,7 +170,7 @@ pub use token::{get_next_token, parse_string_literal, InputStream, Token, Tokeni #[cfg(feature = "internals")] #[deprecated(note = "this type is volatile and may change")] pub use ast::{ - BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallInfo, Ident, IdentX, ReturnType, ScriptFnDef, + BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt, }; @@ -178,7 +180,7 @@ pub use engine::{Imports, Limits, State as EvalState}; #[cfg(feature = "internals")] #[deprecated(note = "this type is volatile and may change")] -pub use module::ModuleRef; +pub use module::NamespaceRef; /// _[INTERNALS]_ Alias to [`smallvec::SmallVec<[T; 4]>`](https://crates.io/crates/smallvec), /// which is a specialized `Vec` backed by a small, fixed-size array when there are <= 4 items stored. diff --git a/src/module/mod.rs b/src/module/mod.rs index f9d28d87..08b4aca2 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -55,8 +55,8 @@ pub struct FuncInfo { pub types: Option>, } -/// An imported module, which may contain variables, sub-modules, -/// external Rust functions, and script-defined functions. +/// A module which may contain variables, sub-modules, external Rust functions, +/// and/or script-defined functions. /// /// Not available under the `no_module` feature. #[derive(Default, Clone)] @@ -253,7 +253,7 @@ impl Module { self } - /// Get a reference to a modules-qualified variable. + /// Get a reference to a namespace-qualified variable. /// Name and Position in `EvalAltResult` are None and must be set afterwards. /// /// The `u64` hash is calculated by the function `crate::calc_native_fn_hash`. @@ -1105,7 +1105,7 @@ impl Module { } } - /// Get a modules-qualified function. + /// Get a namespace-qualified function. /// Name and Position in `EvalAltResult` are None and must be set afterwards. /// /// The `u64` hash is calculated by the function `crate::calc_native_fn_hash` and must match @@ -1435,7 +1435,7 @@ impl Module { if let Some(param_types) = types { assert_eq!(*params, param_types.len()); - // Qualified Rust functions are indexed in two steps: + // Namespace-qualified Rust functions are indexed in two steps: // 1) Calculate a hash in a similar manner to script-defined functions, // i.e. qualifiers + function name + number of arguments. let hash_qualified_script = @@ -1516,21 +1516,21 @@ impl Module { } } -/// _[INTERNALS]_ A chain of module names to qualify a variable or function call. +/// _[INTERNALS]_ A chain of module names to namespace-qualify a variable or function call. /// Exported under the `internals` feature only. /// /// A `u64` hash key is cached for quick search purposes. /// -/// A `StaticVec` is used because most module-level access contains only one level, +/// A `StaticVec` is used because most namespace-qualified access contains only one level, /// and it is wasteful to always allocate a `Vec` with one element. /// /// ## WARNING /// /// This type is volatile and may change. #[derive(Clone, Eq, PartialEq, Default, Hash)] -pub struct ModuleRef(StaticVec, Option); +pub struct NamespaceRef(StaticVec, Option); -impl fmt::Debug for ModuleRef { +impl fmt::Debug for NamespaceRef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f)?; @@ -1542,7 +1542,7 @@ impl fmt::Debug for ModuleRef { } } -impl Deref for ModuleRef { +impl Deref for NamespaceRef { type Target = StaticVec; fn deref(&self) -> &Self::Target { @@ -1550,13 +1550,13 @@ impl Deref for ModuleRef { } } -impl DerefMut for ModuleRef { +impl DerefMut for NamespaceRef { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl fmt::Display for ModuleRef { +impl fmt::Display for NamespaceRef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for Ident { name, .. } in self.0.iter() { write!(f, "{}{}", name, Token::DoubleColon.syntax())?; @@ -1565,7 +1565,7 @@ impl fmt::Display for ModuleRef { } } -impl From> for ModuleRef { +impl From> for NamespaceRef { fn from(modules: StaticVec) -> Self { Self(modules, None) } @@ -1596,7 +1596,7 @@ impl> AddAssign for Module { } } -impl ModuleRef { +impl NamespaceRef { pub(crate) fn index(&self) -> Option { self.1 } diff --git a/src/optimize.rs b/src/optimize.rs index e2685662..63f856ec 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -1,6 +1,6 @@ //! Module implementing the AST optimizer. -use crate::ast::{BinaryExpr, CustomExpr, Expr, FnCallInfo, ScriptFnDef, Stmt, AST}; +use crate::ast::{BinaryExpr, CustomExpr, Expr, FnCallExpr, ScriptFnDef, Stmt, AST}; use crate::dynamic::Dynamic; use crate::engine::{ Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, @@ -644,7 +644,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr { && x.args.iter().all(Expr::is_constant) // all arguments are constants && !is_valid_identifier(x.name.chars()) // cannot be scripted => { - let FnCallInfo { name, args, .. } = x.as_mut(); + let FnCallExpr { name, args, .. } = x.as_mut(); let arg_values: StaticVec<_> = args.iter().map(|e| e.get_constant_value().unwrap()).collect(); let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect(); @@ -670,7 +670,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr { && state.optimization_level == OptimizationLevel::Full // full optimizations && x.args.iter().all(Expr::is_constant) // all arguments are constants => { - let FnCallInfo { name, args, def_value, .. } = x.as_mut(); + let FnCallExpr { name, args, def_value, .. } = x.as_mut(); // First search for script-defined functions (can override built-in) #[cfg(not(feature = "no_function"))] diff --git a/src/parser.rs b/src/parser.rs index daa73352..ff2c189d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,11 +1,11 @@ //! Main module defining the lexer and parser. use crate::ast::{ - BinaryExpr, CustomExpr, Expr, FnCallInfo, Ident, IdentX, ReturnType, ScriptFnDef, Stmt, AST, + BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt, AST, }; use crate::dynamic::{Dynamic, Union}; use crate::engine::{Engine, KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT}; -use crate::module::ModuleRef; +use crate::module::NamespaceRef; use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::parse_error::{LexError, ParseError, ParseErrorType}; use crate::scope::{EntryType as ScopeEntryType, Scope}; @@ -270,7 +270,7 @@ fn parse_fn_call( lib: &mut FunctionsLib, id: String, capture: bool, - mut namespace: Option>, + mut namespace: Option>, settings: ParseSettings, ) -> Result { let (token, token_pos) = input.peek().unwrap(); @@ -313,7 +313,7 @@ fn parse_fn_call( }; return Ok(Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { name: id.into(), capture, namespace, @@ -360,7 +360,7 @@ fn parse_fn_call( }; return Ok(Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { name: id.into(), capture, namespace, @@ -907,7 +907,7 @@ fn parse_primary( if let Some(ref mut modules) = modules { modules.push(var_name_def); } else { - let mut m: ModuleRef = Default::default(); + let mut m: NamespaceRef = Default::default(); m.push(var_name_def); modules = Some(Box::new(m)); } @@ -934,16 +934,16 @@ fn parse_primary( } match &mut root_expr { - // Cache the hash key for module-qualified variables + // Cache the hash key for namespace-qualified variables Expr::Variable(x) if x.1.is_some() => { let (_, modules, hash, Ident { name, .. }) = x.as_mut(); - let modules = modules.as_mut().unwrap(); + let namespace = modules.as_mut().unwrap(); // Qualifiers + variable name - *hash = calc_script_fn_hash(modules.iter().map(|v| v.name.as_str()), name, 0); + *hash = calc_script_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0); #[cfg(not(feature = "no_module"))] - modules.set_index(state.find_module(&modules[0].name)); + namespace.set_index(state.find_module(&namespace[0].name)); } _ => (), } @@ -1001,7 +1001,7 @@ fn parse_unary( args.push(expr); Ok(Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { name: op.into(), native_only: true, namespace: None, @@ -1030,7 +1030,7 @@ fn parse_unary( let hash = calc_script_fn_hash(empty(), op, 1); Ok(Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { name: op.into(), native_only: true, hash, @@ -1490,7 +1490,7 @@ fn parse_binary_op( let op = op_token.syntax(); let hash = calc_script_fn_hash(empty(), &op, 2); - let op_base = FnCallInfo { + let op_base = FnCallExpr { name: op, native_only: true, capture: false, @@ -1513,7 +1513,7 @@ fn parse_binary_op( | Token::Ampersand | Token::Pipe | Token::XOr => Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { hash, args, ..op_base @@ -1523,7 +1523,7 @@ fn parse_binary_op( // '!=' defaults to true when passed invalid operands Token::NotEqualsTo => Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { hash, args, def_value: Some(true), @@ -1538,7 +1538,7 @@ fn parse_binary_op( | Token::LessThanEqualsTo | Token::GreaterThan | Token::GreaterThanEqualsTo => Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { hash, args, def_value: cmp_def, @@ -1585,7 +1585,7 @@ fn parse_binary_op( Token::Custom(s) if state.engine.custom_keywords.contains_key(&s) => { // Accept non-native functions for custom operators Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { hash, args, native_only: false, @@ -2518,7 +2518,7 @@ fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec, pos: Po let hash = calc_script_fn_hash(empty(), KEYWORD_FN_PTR_CURRY, num_externals + 1); let expr = Expr::FnCall( - Box::new(FnCallInfo { + Box::new(FnCallExpr { name: KEYWORD_FN_PTR_CURRY.into(), hash, args, diff --git a/src/token.rs b/src/token.rs index a27dcd82..f109dc97 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1735,7 +1735,7 @@ impl Engine { engine: self, state: TokenizeState { #[cfg(not(feature = "unchecked"))] - max_string_size: self.limits_set.max_string_size, + max_string_size: self.limits.max_string_size, #[cfg(feature = "unchecked")] max_string_size: 0, non_unary: false, diff --git a/src/utils.rs b/src/utils.rs index 385c4536..6cfd4d2f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -55,7 +55,7 @@ impl BuildHasher for StraightHasherBuilder { } } -/// _[INTERNALS]_ Calculate a `u64` hash key from a module-qualified function name and parameter types. +/// _[INTERNALS]_ Calculate a `u64` hash key from a namespace-qualified function name and parameter types. /// Exported under the `internals` feature only. /// /// Module names are passed in via `&str` references from an iterator. @@ -73,8 +73,8 @@ pub fn calc_native_fn_hash<'a>( calc_fn_hash(modules, fn_name, None, params) } -/// _[INTERNALS]_ Calculate a `u64` hash key from a module-qualified function name and the number of parameters, -/// but no parameter types. +/// _[INTERNALS]_ Calculate a `u64` hash key from a namespace-qualified function name +/// and the number of parameters, but no parameter types. /// Exported under the `internals` feature only. /// /// Module names are passed in via `&str` references from an iterator. @@ -92,7 +92,7 @@ pub fn calc_script_fn_hash<'a>( calc_fn_hash(modules, fn_name, Some(num), empty()) } -/// Calculate a `u64` hash key from a module-qualified function name and parameter types. +/// Calculate a `u64` hash key from a namespace-qualified function name and parameter types. /// /// Module names are passed in via `&str` references from an iterator. /// Parameter types are passed in via `TypeId` values from an iterator.