From a0979d0c356c9aabd656d6db3af8a7b7cc31e908 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 25 Nov 2020 09:36:06 +0800 Subject: [PATCH] Code cleanup --- src/ast.rs | 32 ++++++++++++------ src/dynamic.rs | 18 +++++----- src/engine.rs | 45 ++++++++++++------------- src/engine_api.rs | 6 ++-- src/engine_settings.rs | 16 ++++----- src/fn_args.rs | 2 +- src/fn_call.rs | 2 +- src/fn_native.rs | 15 +++++---- src/fn_register.rs | 10 +++--- src/lib.rs | 24 ++++++++------ src/module/mod.rs | 40 +++++++++++++---------- src/optimize.rs | 67 ++++++++++++++++++++------------------ src/packages/fn_basic.rs | 4 +-- src/packages/iter_basic.rs | 2 +- src/parse_error.rs | 6 ++-- src/parser.rs | 42 ++++++++++++------------ src/result.rs | 12 +++---- src/scope.rs | 2 +- src/syntax.rs | 2 +- 19 files changed, 187 insertions(+), 160 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index cc5a79be..b15cfe68 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -41,7 +41,7 @@ pub enum FnAccess { } impl FnAccess { - /// Is this access mode private? + /// Is this access mode [private][FnAccess::Private]? #[inline(always)] pub fn is_private(self) -> bool { match self { @@ -49,7 +49,7 @@ impl FnAccess { Self::Public => false, } } - /// Is this access mode public? + /// Is this access mode [public][FnAccess::Public]? #[inline(always)] pub fn is_public(self) -> bool { match self { @@ -482,7 +482,7 @@ impl AST { #[inline(always)] pub fn iter_functions<'a>( &'a self, - ) -> impl Iterator)> + 'a { + ) -> impl Iterator + 'a { self.1.iter_script_fn() } /// Clear all function definitions in the [`AST`]. @@ -528,7 +528,12 @@ impl AsRef for AST { } } -/// An identifier containing a string name and a position. +/// _(INTERNALS)_ An identifier containing a [string][String] name and a [position][Position]. +/// Exported under the `internals` feature only. +/// +/// ## WARNING +/// +/// This type is volatile and may change. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Ident { pub name: String, @@ -542,7 +547,12 @@ impl Ident { } } -/// An identifier containing an immutable name and a position. +/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position]. +/// Exported under the `internals` feature only. +/// +/// ## WARNING +/// +/// This type is volatile and may change. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct IdentX { pub name: ImmutableString, @@ -650,7 +660,7 @@ impl Stmt { _ => false, } } - /// Get the [`Position`] of this statement. + /// Get the [position][`Position`] of this statement. pub fn position(&self) -> Position { match self { Self::Noop(pos) @@ -679,7 +689,7 @@ impl Stmt { Self::Share(x) => x.pos, } } - /// Override the [`Position`] of this statement. + /// Override the [position][`Position`] of this statement. pub fn set_position(&mut self, new_pos: Position) -> &mut Self { match self { Self::Noop(pos) @@ -742,6 +752,8 @@ impl Stmt { } } /// Is this statement _pure_? + /// + /// A pure statement has no side effects. pub fn is_pure(&self) -> bool { match self { Self::Noop(_) => true, @@ -967,7 +979,7 @@ impl Expr { _ => None, } } - /// Get the [`Position`] of the expression. + /// Get the [position][`Position`] of the expression. pub fn position(&self) -> Position { match self { Self::Expr(x) => x.position(), @@ -997,7 +1009,7 @@ impl Expr { Self::Custom(_, pos) => *pos, } } - /// Override the [`Position`] of the expression. + /// Override the [position][`Position`] of the expression. pub fn set_position(&mut self, new_pos: Position) -> &mut Self { match self { Self::Expr(x) => { @@ -1089,7 +1101,7 @@ impl Expr { _ => false, } } - /// Is a particular token allowed as a postfix operator to this expression? + /// Is a particular [token][Token] allowed as a postfix operator to this expression? pub fn is_valid_postfix(&self, token: &Token) -> bool { match self { Self::Expr(x) => x.is_valid_postfix(token), diff --git a/src/dynamic.rs b/src/dynamic.rs index 412acafb..9360f0a8 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -43,7 +43,7 @@ mod private { /// Trait to represent any type. /// /// Currently, [`Variant`] is not [`Send`] nor [`Sync`], so it can practically be any type. -/// Turn on the [`Sync`] feature to restrict it to only types that implement [`Send`] `+` [`Sync`]. +/// Turn on the `sync` feature to restrict it to only types that implement [`Send`] `+` [`Sync`]. #[cfg(not(feature = "sync"))] pub trait Variant: Any + private::Sealed { /// Convert this [`Variant`] trait object to [`&dyn Any`][Any]. @@ -268,7 +268,7 @@ impl Dynamic { /// /// # Panics or Deadlocks When Value is Shared /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. pub fn type_id(&self) -> TypeId { match &self.0 { @@ -301,7 +301,7 @@ impl Dynamic { /// /// # Panics or Deadlocks When Value is Shared /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. pub fn type_name(&self) -> &'static str { match &self.0 { @@ -654,7 +654,7 @@ impl Dynamic { Self(Union::Variant(Box::new(boxed))) } /// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>` - /// or [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>` depending on the [`Sync`] feature. + /// or [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>` depending on the `sync` feature. /// /// Shared [`Dynamic`] values are relatively cheap to clone as they simply increment the /// reference counts. @@ -686,7 +686,7 @@ impl Dynamic { /// /// # Panics or Deadlocks /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. /// /// These normally shouldn't occur since most operations in Rhai is single-threaded. @@ -819,7 +819,7 @@ impl Dynamic { /// Panics if the cast fails (e.g. the type of the actual value is not the /// same as the specified type). /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. /// /// These normally shouldn't occur since most operations in Rhai is single-threaded. @@ -900,7 +900,7 @@ impl Dynamic { /// /// ## Note /// - /// Under the [`Sync`] feature, shared values use [`RwLock`][std::sync::RwLock] and they are never locked. + /// Under the `sync` feature, shared values use [`RwLock`][std::sync::RwLock] and they are never locked. /// Access just waits until the [`RwLock`][std::sync::RwLock] is released. /// So this method always returns [`false`] under [`Sync`]. #[inline(always)] @@ -924,7 +924,7 @@ impl Dynamic { /// /// # Panics or Deadlocks When Value is Shared /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. #[inline(always)] pub fn read_lock(&self) -> Option> { @@ -956,7 +956,7 @@ impl Dynamic { /// /// # Panics or Deadlocks When Value is Shared /// - /// Under the [`Sync`] feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). + /// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1). /// Otherwise, this call panics if the data is currently borrowed for write. #[inline(always)] pub fn write_lock(&mut self) -> Option> { diff --git a/src/engine.rs b/src/engine.rs index a6ad78d1..35f50b16 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -40,7 +40,7 @@ use crate::Map; #[cfg(not(feature = "no_object"))] pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical -/// _(INTERNALS)_ A stack of imported modules. +/// _(INTERNALS)_ A stack of imported [modules][Module]. /// Exported under the `internals` feature only. /// /// ## WARNING @@ -49,21 +49,22 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical // // # Implementation Notes // -// We cannot use &str or Cow here because `eval` may load a module and the module name will live beyond -// the AST of the eval script text. The best we can do is a shared reference. +// We cannot use &str or Cow here because `eval` may load a [module][Module] and +// the module name will live beyond the AST of the eval script text. +// The best we can do is a shared reference. #[derive(Debug, Clone, Default)] pub struct Imports(Option)>>); impl Imports { - /// Get the length of this stack of imported modules. + /// Get the length of this stack of imported [modules][Module]. pub fn len(&self) -> usize { self.0.as_ref().map_or(0, StaticVec::len) } - /// Is this stack of imported modules empty? + /// Is this stack of imported [modules][Module] empty? pub fn is_empty(&self) -> bool { self.0.as_ref().map_or(true, StaticVec::is_empty) } - /// Get the imported module at a particular index. + /// Get the imported [modules][Module] at a particular index. pub fn get(&self, index: usize) -> Option> { self.0 .as_ref() @@ -71,7 +72,7 @@ impl Imports { .map(|(_, m)| m) .cloned() } - /// Get the index of an imported module by name. + /// Get the index of an imported [modules][Module] by name. pub fn find(&self, name: &str) -> Option { self.0.as_ref().and_then(|x| { x.iter() @@ -81,7 +82,7 @@ impl Imports { .map(|(index, _)| index) }) } - /// Push an imported module onto the stack. + /// Push an imported [modules][Module] onto the stack. pub fn push(&mut self, name: impl Into, module: impl Into>) { if self.0.is_none() { self.0 = Some(Default::default()); @@ -89,13 +90,13 @@ impl Imports { self.0.as_mut().unwrap().push((name.into(), module.into())); } - /// Truncate the stack of imported modules to a particular length. + /// Truncate the stack of imported [modules][Module] to a particular length. pub fn truncate(&mut self, size: usize) { if self.0.is_some() { self.0.as_mut().unwrap().truncate(size); } } - /// Get an iterator to this stack of imported modules in reverse order. + /// Get an iterator to this stack of imported [modules][Module] in reverse order. #[allow(dead_code)] pub fn iter<'a>(&'a self) -> impl Iterator)> + 'a { self.0.iter().flat_map(|lib| { @@ -104,22 +105,22 @@ impl Imports { .map(|(name, module)| (name.clone(), module.clone())) }) } - /// Get an iterator to this stack of imported modules in reverse order. + /// Get an iterator to this stack of imported [modules][Module] in reverse order. #[allow(dead_code)] pub(crate) fn iter_raw<'a>( &'a self, ) -> impl Iterator)> + 'a { self.0.iter().flat_map(|lib| lib.iter().rev().cloned()) } - /// Get a consuming iterator to this stack of imported modules in reverse order. + /// Get a consuming iterator to this stack of imported [modules][Module] in reverse order. pub fn into_iter(self) -> impl Iterator)> { self.0.into_iter().flat_map(|lib| lib.into_iter().rev()) } - /// Add a stream of imported modules. + /// Add a stream of imported [modules][Module]. pub fn extend(&mut self, stream: impl Iterator)>) { self.0.as_mut().unwrap().extend(stream) } - /// Does the specified function hash key exist in this stack of imported modules? + /// Does the specified function hash key exist in this stack of imported [modules][Module]? #[allow(dead_code)] pub fn contains_fn(&self, hash: u64) -> bool { self.0.as_ref().map_or(false, |x| { @@ -132,14 +133,14 @@ impl Imports { .as_ref() .and_then(|x| x.iter().rev().find_map(|(_, m)| m.get_qualified_fn(hash))) } - /// Does the specified TypeId iterator exist in this stack of imported modules? + /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of imported [modules][Module]? #[allow(dead_code)] pub fn contains_iter(&self, id: TypeId) -> bool { self.0.as_ref().map_or(false, |x| { x.iter().any(|(_, m)| m.contains_qualified_iter(id)) }) } - /// Get the specified TypeId iterator. + /// Get the specified [`TypeId`][std::any::TypeId] iterator. pub fn get_iter(&self, id: TypeId) -> Option { self.0 .as_ref() @@ -462,7 +463,7 @@ impl> From for Target<'_> { } } -/// _(INTERNALS)_ A type that holds all the current states of the Engine. +/// _(INTERNALS)_ A type that holds all the current states of the [`Engine`]. /// Exported under the `internals` feature only. /// /// ## WARNING @@ -512,17 +513,17 @@ pub struct Limits { pub max_function_expr_depth: usize, /// Maximum number of operations allowed to run (0 = unlimited). pub max_operations: u64, - /// Maximum number of modules allowed to load. + /// Maximum number of [modules][Module] allowed to load. /// Not available under `no_module`. #[cfg(not(feature = "no_module"))] pub max_modules: usize, - /// Maximum length of a string (0 = unlimited). + /// Maximum length of a [string][ImmutableString] (0 = unlimited). pub max_string_size: usize, - /// Maximum length of an array (0 = unlimited). + /// Maximum length of an [array][Array] (0 = unlimited). /// Not available under `no_index`. #[cfg(not(feature = "no_index"))] pub max_array_size: usize, - /// Maximum number of properties in a map (0 = unlimited). + /// Maximum number of properties in an [object map][Map] (0 = unlimited). /// Not available under `no_object`. #[cfg(not(feature = "no_object"))] pub max_map_size: usize, @@ -578,7 +579,7 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, /// [`Engine`] is re-entrant. /// /// Currently, [`Engine`] is neither [`Send`] nor [`Sync`]. -/// Use the [`Sync`] feature to make it [`Send`] `+` [`Sync`]. +/// Use the `sync` feature to make it [`Send`] `+` [`Sync`]. /// /// # Example /// diff --git a/src/engine_api.rs b/src/engine_api.rs index b3227c58..8169d791 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -37,10 +37,10 @@ impl Engine { /// /// ## WARNING - Low Level API /// - /// This function is very low level. It takes a list of [`TypeId`]'s indicating the actual types of the parameters. + /// This function is very low level. It takes a list of [`TypeId`][std::any::TypeId]'s indicating the actual types of the parameters. /// /// Arguments are simply passed in as a mutable array of [`&mut Dynamic`][Dynamic], - /// The arguments are guaranteed to be of the correct types matching the [`TypeId`]'s. + /// The arguments are guaranteed to be of the correct types matching the [`TypeId`][std::any::TypeId]'s. /// /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// @@ -1639,7 +1639,7 @@ impl Engine { .lib() .iter_fn() .filter(|f| f.func.is_script()) - .map(|f| (**f.func.get_fn_def()).clone()) + .map(|f| f.func.get_fn_def().clone()) .collect(); #[cfg(feature = "no_function")] diff --git a/src/engine_settings.rs b/src/engine_settings.rs index 319dbfb9..6b6f8ba7 100644 --- a/src/engine_settings.rs +++ b/src/engine_settings.rs @@ -72,7 +72,7 @@ impl Engine { pub fn max_operations(&self) -> u64 { self.limits.max_operations } - /// Set the maximum number of imported modules allowed for a script. + /// Set the maximum number of imported [modules][crate::Module] allowed for a script. #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_module"))] #[inline(always)] @@ -80,7 +80,7 @@ impl Engine { self.limits.max_modules = modules; self } - /// The maximum number of imported modules allowed for a script. + /// The maximum number of imported [modules][crate::Module] allowed for a script. #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_module"))] #[inline(always)] @@ -123,20 +123,20 @@ impl Engine { pub fn max_function_expr_depth(&self) -> usize { self.limits.max_function_expr_depth } - /// Set the maximum length of strings (0 for unlimited). + /// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self { self.limits.max_string_size = if max_size == usize::MAX { 0 } else { max_size }; self } - /// The maximum length of strings (0 for unlimited). + /// The maximum length of [strings][crate::ImmutableString] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[inline(always)] pub fn max_string_size(&self) -> usize { self.limits.max_string_size } - /// Set the maximum length of arrays (0 for unlimited). + /// Set the maximum length of [arrays][crate::Array] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_index"))] #[inline(always)] @@ -144,14 +144,14 @@ impl Engine { self.limits.max_array_size = if max_size == usize::MAX { 0 } else { max_size }; self } - /// The maximum length of arrays (0 for unlimited). + /// The maximum length of [arrays][crate::Array] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_index"))] #[inline(always)] pub fn max_array_size(&self) -> usize { self.limits.max_array_size } - /// Set the maximum length of object maps (0 for unlimited). + /// Set the maximum length of [object maps][crate::Map] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_object"))] #[inline(always)] @@ -159,7 +159,7 @@ impl Engine { self.limits.max_map_size = if max_size == usize::MAX { 0 } else { max_size }; self } - /// The maximum length of object maps (0 for unlimited). + /// The maximum length of [object maps][crate::Map] (0 for unlimited). #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_object"))] #[inline(always)] diff --git a/src/fn_args.rs b/src/fn_args.rs index 8c45a98a..876c59ba 100644 --- a/src/fn_args.rs +++ b/src/fn_args.rs @@ -6,7 +6,7 @@ use crate::dynamic::Variant; use crate::{Dynamic, StaticVec}; /// Trait that represents arguments to a function call. -/// Any data type that can be converted into a `Vec` can be used +/// Any data type that can be converted into a [`Vec`]`<`[`Dynamic`]`>` can be used /// as arguments to a function call. pub trait FuncArgs { /// Convert to a [`StaticVec`]`<`[`Dynamic`]`>` of the function call arguments. diff --git a/src/fn_call.rs b/src/fn_call.rs index 1c629bf2..13514dcb 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1166,7 +1166,7 @@ impl Engine { } } - f.get_native_fn().clone()((self, &*mods, lib).into(), args.as_mut()) + f.get_native_fn()((self, &*mods, lib).into(), args.as_mut()) } Some(_) => unreachable!(), None if def_val.is_some() => Ok(def_val.unwrap().clone()), diff --git a/src/fn_native.rs b/src/fn_native.rs index e605df82..bb34c017 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -45,7 +45,7 @@ pub type Locked = crate::stdlib::cell::RefCell; #[cfg(feature = "sync")] pub type Locked = crate::stdlib::sync::RwLock; -/// Context of native Rust function call. +/// Context of a native Rust function call. #[derive(Debug, Copy, Clone)] pub struct NativeCallContext<'e, 'a, 'm, 'pm: 'm> { engine: &'e Engine, @@ -207,6 +207,7 @@ pub fn shared_take(value: Shared) -> T { shared_try_take(value).map_err(|_| ()).unwrap() } +/// Arguments to a function call, which is a list of [`&mut Dynamic`][Dynamic]. pub type FnCallArgs<'a> = [&'a mut Dynamic]; /// A general function pointer, which may carry additional (i.e. curried) argument values @@ -488,9 +489,9 @@ impl CallableFunction { /// /// Panics if the [`CallableFunction`] is not [`Pure`][CallableFunction::Pure] or /// [`Method`][CallableFunction::Method]. - pub fn get_native_fn(&self) -> &Shared { + pub fn get_native_fn(&self) -> &FnAny { match self { - Self::Pure(f) | Self::Method(f) => f, + Self::Pure(f) | Self::Method(f) => f.as_ref(), Self::Iterator(_) | Self::Plugin(_) => unreachable!(), #[cfg(not(feature = "no_function"))] @@ -503,10 +504,10 @@ impl CallableFunction { /// /// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script]. #[cfg(not(feature = "no_function"))] - pub fn get_fn_def(&self) -> &Shared { + pub fn get_fn_def(&self) -> &ScriptFnDef { match self { Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => unreachable!(), - Self::Script(f) => f, + Self::Script(f) => f.as_ref(), } } /// Get a reference to an iterator function. @@ -528,9 +529,9 @@ impl CallableFunction { /// # Panics /// /// Panics if the [`CallableFunction`] is not [`Plugin`][CallableFunction::Plugin]. - pub fn get_plugin_fn<'s>(&'s self) -> &Shared { + pub fn get_plugin_fn<'s>(&'s self) -> &FnPlugin { match self { - Self::Plugin(f) => f, + Self::Plugin(f) => f.as_ref(), Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => unreachable!(), #[cfg(not(feature = "no_function"))] diff --git a/src/fn_register.rs b/src/fn_register.rs index 3a6db5f8..4021fa57 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -10,9 +10,9 @@ use crate::{ Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, NativeCallContext, }; -/// Trait to register custom functions with the `Engine`. +/// Trait to register custom functions with the [`Engine`]. pub trait RegisterFn { - /// Register a custom function with the `Engine`. + /// Register a custom function with the [`Engine`]. /// /// # Example /// @@ -42,9 +42,9 @@ pub trait RegisterFn { fn register_fn(&mut self, name: &str, f: FN) -> &mut Self; } -/// Trait to register fallible custom functions returning `Result>` with the `Engine`. +/// Trait to register fallible custom functions returning [`Result`]`<`[`Dynamic`]`, `[`Box`]`<`[`EvalAltResult`]`>>` with the [`Engine`]. pub trait RegisterResultFn { - /// Register a custom fallible function with the `Engine`. + /// Register a custom fallible function with the [`Engine`]. /// /// # Example /// @@ -75,7 +75,7 @@ pub trait RegisterResultFn { // These types are used to build a unique _marker_ tuple type for each combination // of function parameter types in order to make each trait implementation unique. // That is because stable Rust currently does not allow distinguishing implementations -// based purely on parameter types of traits (Fn, FnOnce and FnMut). +// based purely on parameter types of traits (`Fn`, `FnOnce` and `FnMut`). // // For example: // diff --git a/src/lib.rs b/src/lib.rs index f4aa7721..601f9d5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,20 +83,22 @@ mod token; mod r#unsafe; mod utils; -/// The system integer type. It is defined as `i64`. +/// The system integer type. It is defined as [`i64`]. /// -/// If the `only_i32` feature is enabled, this will be `i32` instead. +/// 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. +/// 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. +/// If the `only_i32` feature is not used, this will be `i64` instead. #[cfg(feature = "only_i32")] pub type INT = i32; -/// The system floating-point type. It is defined as `f64`. +/// The system floating-point type. It is defined as [`f64`]. +/// +/// If the `f32_float` feature is enabled, this will be [`i32`] instead. /// /// Not available under the `no_float` feature. #[cfg(not(feature = "no_float"))] @@ -104,7 +106,9 @@ 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. +/// It is defined as [`f32`] since the `f32_float` feature is used. +/// +/// If the `f32_float` feature is not used, this will be `f64` instead. /// /// Not available under the `no_float` feature. #[cfg(not(feature = "no_float"))] @@ -138,13 +142,13 @@ pub use rhai_codegen::*; #[cfg(not(feature = "no_function"))] pub use fn_func::Func; -/// Variable-sized array of `Dynamic` values. +/// Variable-sized array of [`Dynamic`] values. /// /// Not available under the `no_index` feature. #[cfg(not(feature = "no_index"))] pub type Array = stdlib::vec::Vec; -/// Hash map of `Dynamic` values with `ImmutableString` keys. +/// Hash map of [`Dynamic`] values with [`ImmutableString`] keys. /// /// Not available under the `no_object` feature. #[cfg(not(feature = "no_object"))] @@ -188,13 +192,13 @@ pub use engine::{Imports, Limits, State as EvalState}; 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. +/// which is a specialized [`Vec`] backed by a small, fixed-size array when there are <= 4 items stored. /// Exported under the `internals` feature only. #[cfg(not(feature = "internals"))] type StaticVec = smallvec::SmallVec<[T; 4]>; /// _(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. +/// which is a specialized [`Vec`] backed by a small, fixed-size array when there are <= 4 items stored. /// Exported under the `internals` feature only. #[cfg(feature = "internals")] pub type StaticVec = smallvec::SmallVec<[T; 4]>; diff --git a/src/module/mod.rs b/src/module/mod.rs index 78e3628c..725bb9fa 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -21,6 +21,9 @@ use crate::{ Dynamic, EvalAltResult, ImmutableString, NativeCallContext, Position, Shared, StaticVec, }; +#[cfg(not(feature = "no_function"))] +use crate::ast::ScriptFnDef; + #[cfg(not(feature = "no_index"))] use crate::Array; @@ -28,9 +31,6 @@ use crate::Array; #[cfg(not(feature = "no_object"))] use crate::Map; -#[cfg(not(feature = "no_function"))] -pub type SharedScriptFnDef = Shared; - /// A type representing the namespace of a function. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub enum FnNamespace { @@ -47,7 +47,7 @@ impl Default for FnNamespace { } impl FnNamespace { - /// Is this namespace global? + /// Is this namespace [global][FnNamespace::Global]? #[inline(always)] pub fn is_global(self) -> bool { match self { @@ -55,7 +55,7 @@ impl FnNamespace { Self::Internal => false, } } - /// Is this namespace internal? + /// Is this namespace [internal][FnNamespace::Internal]? #[inline(always)] pub fn is_internal(self) -> bool { match self { @@ -357,7 +357,9 @@ impl Module { /// If there is an existing function of the same name and number of arguments, it is replaced. #[cfg(not(feature = "no_function"))] #[inline] - pub(crate) fn set_script_fn(&mut self, fn_def: SharedScriptFnDef) -> u64 { + pub(crate) fn set_script_fn(&mut self, fn_def: impl Into>) -> u64 { + let fn_def = fn_def.into(); + // None + function name + number of arguments. let num_params = fn_def.params.len(); let hash_script = crate::calc_script_fn_hash(empty(), &fn_def.name, num_params); @@ -392,7 +394,7 @@ impl Module { name: &str, num_params: usize, public_only: bool, - ) -> Option<&SharedScriptFnDef> { + ) -> Option<&ScriptFnDef> { self.functions .values() .find( @@ -1527,12 +1529,12 @@ impl Module { /// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]). /// 3) Function name (as string slice). /// 4) Number of parameters. - /// 5) Shared reference to function definition [`ScriptFnDef`][crate::ScriptFnDef]. + /// 5) Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef]. #[cfg(not(feature = "no_function"))] #[inline(always)] pub(crate) fn iter_script_fn<'a>( &'a self, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.functions.values().filter(|f| f.func.is_script()).map( |FuncInfo { namespace, @@ -1547,7 +1549,7 @@ impl Module { *access, name.as_str(), *params, - func.get_fn_def().clone(), + func.get_fn_def(), ) }, ) @@ -1584,14 +1586,14 @@ impl Module { /// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]). /// 3) Function name (as string slice). /// 4) Number of parameters. - /// 5) _(INTERNALS)_ Shared reference to function definition [`ScriptFnDef`][crate::ScriptFnDef]. + /// 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)] pub fn iter_script_fn_info( &self, - ) -> impl Iterator { + ) -> impl Iterator { self.iter_script_fn() } @@ -1653,14 +1655,16 @@ impl Module { // Non-private functions defined become module functions #[cfg(not(feature = "no_function"))] { - ast.iter_functions() - .filter(|(_, access, _, _, _)| !access.is_private()) - .for_each(|(_, _, _, _, func)| { + ast.lib() + .functions + .values() + .filter(|FuncInfo { access, func, .. }| !access.is_private() && func.is_script()) + .for_each(|FuncInfo { func, .. }| { // Encapsulate AST environment - let mut func = func.as_ref().clone(); + let mut func = func.get_fn_def().clone(); func.lib = Some(ast.shared_lib()); func.mods = func_mods.clone(); - module.set_script_fn(func.into()); + module.set_script_fn(func); }); } @@ -1827,7 +1831,7 @@ impl Module { } } -/// _(INTERNALS)_ A chain of module names to namespace-qualify a variable or function call. +/// _(INTERNALS)_ A chain of [module][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. diff --git a/src/optimize.rs b/src/optimize.rs index 19ee51ce..218c307b 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -1,4 +1,4 @@ -//! Module implementing the AST optimizer. +//! Module implementing the [`AST`] optimizer. use crate::ast::{Expr, ScriptFnDef, Stmt}; use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF}; @@ -32,18 +32,18 @@ pub enum OptimizationLevel { } impl OptimizationLevel { - /// Is the `OptimizationLevel` None. + /// Is the `OptimizationLevel` [`None`][OptimizationLevel::None]? #[inline(always)] pub fn is_none(self) -> bool { self == Self::None } - /// Is the `OptimizationLevel` Simple. + /// Is the `OptimizationLevel` [`Simple`][OptimizationLevel::Simple]? #[cfg(not(feature = "no_optimize"))] #[inline(always)] pub fn is_simple(self) -> bool { self == Self::Simple } - /// Is the `OptimizationLevel` Full. + /// Is the `OptimizationLevel` [`Full`][OptimizationLevel::Full]? #[cfg(not(feature = "no_optimize"))] #[inline(always)] pub fn is_full(self) -> bool { @@ -54,13 +54,13 @@ impl OptimizationLevel { /// Mutable state throughout an optimization pass. #[derive(Debug, Clone)] struct State<'a> { - /// Has the AST been changed during this pass? + /// Has the [`AST`] been changed during this pass? changed: bool, /// Collection of constants to use for eager function evaluations. constants: Vec<(String, Expr)>, - /// An `Engine` instance for eager function evaluation. + /// An [`Engine`] instance for eager function evaluation. engine: &'a Engine, - /// Library of script-defined functions. + /// [Module] containing script-defined functions. lib: &'a [&'a Module], /// Optimization level. optimization_level: OptimizationLevel, @@ -83,12 +83,12 @@ impl<'a> State<'a> { pub fn reset(&mut self) { self.changed = false; } - /// Set the AST state to be dirty (i.e. changed). + /// Set the [`AST`] state to be dirty (i.e. changed). #[inline(always)] pub fn set_dirty(&mut self) { self.changed = true; } - /// Is the AST dirty (i.e. changed)? + /// Is the [`AST`] dirty (i.e. changed)? #[inline(always)] pub fn is_dirty(&self) -> bool { self.changed @@ -147,7 +147,7 @@ fn call_fn_with_constant_arguments( .map(|(v, _)| v) } -/// Optimize a block of statements. +/// Optimize a block of [statements][crate::ast::Stmt]. fn optimize_stmt_block( mut statements: Vec, pos: Position, @@ -264,7 +264,7 @@ fn optimize_stmt_block( } } -/// Optimize a statement. +/// Optimize a [statement][crate::ast::Stmt]. fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) { match stmt { // expr op= expr @@ -460,7 +460,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) { } } -/// Optimize an expression. +/// Optimize an [expression][crate::ast::Expr]. fn optimize_expr(expr: &mut Expr, state: &mut State) { // These keywords are handled specially const DONT_EVAL_KEYWORDS: &[&str] = &[ @@ -724,7 +724,8 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) { } } -fn optimize( +/// Optimize a block of [statements][crate::ast::Stmt] at top level. +fn optimize_top_level( mut statements: Vec, engine: &Engine, scope: &Scope, @@ -815,7 +816,7 @@ fn optimize( statements } -/// Optimize an AST. +/// Optimize an [`AST`]. pub fn optimize_into_ast( engine: &Engine, scope: &Scope, @@ -839,19 +840,16 @@ pub fn optimize_into_ast( _functions .iter() - .map(|fn_def| { - ScriptFnDef { - name: fn_def.name.clone(), - access: fn_def.access, - body: Default::default(), - params: fn_def.params.clone(), - #[cfg(not(feature = "no_closure"))] - externals: fn_def.externals.clone(), - lib: None, - #[cfg(not(feature = "no_module"))] - mods: Default::default(), - } - .into() + .map(|fn_def| ScriptFnDef { + name: fn_def.name.clone(), + access: fn_def.access, + body: Default::default(), + params: fn_def.params.clone(), + #[cfg(not(feature = "no_closure"))] + externals: fn_def.externals.clone(), + lib: None, + #[cfg(not(feature = "no_module"))] + mods: Default::default(), }) .for_each(|fn_def| { lib2.set_script_fn(fn_def); @@ -863,8 +861,13 @@ pub fn optimize_into_ast( let pos = fn_def.body.position(); // Optimize the function body - let mut body = - optimize(vec![fn_def.body], engine, &Scope::new(), &[&lib2], level); + let mut body = optimize_top_level( + vec![fn_def.body], + engine, + &Scope::new(), + &[&lib2], + level, + ); // {} -> Noop fn_def.body = match body.pop().unwrap_or_else(|| Stmt::Noop(pos)) { @@ -879,14 +882,14 @@ pub fn optimize_into_ast( // All others stmt => stmt, }; - fn_def.into() + fn_def }) .for_each(|fn_def| { module.set_script_fn(fn_def); }); } else { _functions.into_iter().for_each(|fn_def| { - module.set_script_fn(fn_def.into()); + module.set_script_fn(fn_def); }); } @@ -902,7 +905,7 @@ pub fn optimize_into_ast( match level { OptimizationLevel::None => statements, OptimizationLevel::Simple | OptimizationLevel::Full => { - optimize(statements, engine, &scope, &[&lib], level) + optimize_top_level(statements, engine, &scope, &[&lib], level) } }, lib, diff --git a/src/packages/fn_basic.rs b/src/packages/fn_basic.rs index 9402413c..ca153a97 100644 --- a/src/packages/fn_basic.rs +++ b/src/packages/fn_basic.rs @@ -5,7 +5,7 @@ use crate::{calc_script_fn_hash, def_package, FnPtr, ImmutableString, NativeCall #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_object"))] -use crate::{module::SharedScriptFnDef, stdlib::collections::HashMap, Array, Map}; +use crate::{ast::ScriptFnDef, stdlib::collections::HashMap, Array, Map}; def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, { combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions); @@ -54,7 +54,7 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> Array { fn make_metadata( dict: &HashMap<&str, ImmutableString>, namespace: Option, - f: SharedScriptFnDef, + f: &ScriptFnDef, ) -> Map { let mut map = Map::with_capacity(6); diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 4ae548e2..f2e839da 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -26,7 +26,7 @@ where fn next(&mut self) -> Option { if self.0 < self.1 { let v = self.0.clone(); - self.0 = &v + &self.2; + self.0 = self.0.add(&self.2); Some(v) } else { None diff --git a/src/parse_error.rs b/src/parse_error.rs index 010864cf..966a3649 100644 --- a/src/parse_error.rs +++ b/src/parse_error.rs @@ -68,10 +68,10 @@ impl LexError { Self::ImproperSymbol(_, _) => "Invalid symbol encountered", } } - /// Convert a `&LexError` into a [`ParseError`]. + /// Convert a [`LexError`] into a [`ParseError`]. #[inline(always)] - pub fn into_err(&self, pos: Position) -> ParseError { - ParseError(Box::new(self.clone().into()), pos) + pub fn into_err(self, pos: Position) -> ParseError { + ParseError(Box::new(self.into()), pos) } } diff --git a/src/parser.rs b/src/parser.rs index 10ebf146..57acdb08 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -36,9 +36,10 @@ type PERR = ParseErrorType; type FunctionsLib = HashMap; +/// A type that encapsulates the current state of the parser. #[derive(Debug)] struct ParseState<'e> { - /// Reference to the scripting `Engine`. + /// Reference to the scripting [`Engine`]. engine: &'e Engine, /// Hash that uniquely identifies a script. script_hash: u64, @@ -57,7 +58,7 @@ struct ParseState<'e> { /// All consequent calls to `access_var` will not be affected #[cfg(not(feature = "no_closure"))] allow_capture: bool, - /// Encapsulates a local stack with imported module names. + /// Encapsulates a local stack with imported [module][crate::Module] names. #[cfg(not(feature = "no_module"))] modules: StaticVec, /// Maximum levels of expression nesting. @@ -70,7 +71,7 @@ struct ParseState<'e> { } impl<'e> ParseState<'e> { - /// Create a new `ParseState`. + /// Create a new [`ParseState`]. #[inline(always)] pub fn new( engine: &'e Engine, @@ -100,12 +101,12 @@ impl<'e> ParseState<'e> { } } - /// Find explicitly declared variable by name in the `ParseState`, searching in reverse order. + /// Find explicitly declared variable by name in the [`ParseState`], searching in reverse order. /// /// If the variable is not present in the scope adds it to the list of external variables /// /// The return value is the offset to be deducted from `Stack::len`, - /// i.e. the top element of the `ParseState` is offset 1. + /// i.e. the top element of the [`ParseState`] is offset 1. /// /// Return `None` when the variable name is not found in the `stack`. #[inline] @@ -144,12 +145,12 @@ impl<'e> ParseState<'e> { } } - /// Find a module by name in the `ParseState`, searching in reverse. + /// Find a module by name in the [`ParseState`], searching in reverse. /// /// Returns the offset to be deducted from `Stack::len`, - /// i.e. the top element of the `ParseState` is offset 1. + /// i.e. the top element of the [`ParseState`] is offset 1. /// - /// Returns `None` when the variable name is not found in the `ParseState`. + /// Returns `None` when the variable name is not found in the [`ParseState`]. /// /// # Panics /// @@ -183,8 +184,8 @@ impl<'e> ParseState<'e> { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] /// A type that encapsulates all the settings for a particular parsing function. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] struct ParseSettings { /// Current position. pos: Position, @@ -230,7 +231,8 @@ impl ParseSettings { } impl Expr { - /// Convert a `Variable` into a `Property`. All other variants are untouched. + /// Convert a [`Variable`][Expr::Variable] into a [`Property`][Expr::Property]. + /// All other variants are untouched. #[cfg(not(feature = "no_object"))] #[inline] fn into_property(self, state: &mut ParseState) -> Self { @@ -246,7 +248,7 @@ impl Expr { } } -/// Consume a particular token, checking that it is the expected one. +/// Consume a particular [token][Token], checking that it is the expected one. fn eat_token(input: &mut TokenStream, token: Token) -> Position { let (t, pos) = input.next().unwrap(); @@ -261,7 +263,7 @@ fn eat_token(input: &mut TokenStream, token: Token) -> Position { pos } -/// Match a particular token, consuming it if matched. +/// Match a particular [token][Token], consuming it if matched. fn match_token(input: &mut TokenStream, token: Token) -> (bool, Position) { let (t, pos) = input.peek().unwrap(); if *t == token { @@ -328,7 +330,7 @@ fn parse_fn_call( .into_err(*token_pos)) } // id( - Token::LexError(err) => return Err(err.into_err(*token_pos)), + Token::LexError(err) => return Err(err.clone().into_err(*token_pos)), // id() Token::RightParen => { eat_token(input, Token::RightParen); @@ -422,7 +424,7 @@ fn parse_fn_call( .into_err(*pos)) } // id(...args - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), // id(...args ??? (_, pos) => { return Err(PERR::MissingToken( @@ -610,7 +612,7 @@ fn parse_index_chain( } } } - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), (_, pos) => Err(PERR::MissingToken( Token::RightBracket.into(), "for a matching [ in this index expression".into(), @@ -672,7 +674,7 @@ fn parse_array_literal( .into_err(*pos), ) } - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), (_, pos) => { return Err(PERR::MissingToken( Token::Comma.into(), @@ -781,7 +783,7 @@ fn parse_map_literal( ) .into_err(*pos)) } - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), (_, pos) => { return Err( PERR::MissingToken(Token::RightBrace.into(), MISSING_RBRACE.into()) @@ -899,7 +901,7 @@ fn parse_switch( .into_err(*pos), ) } - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), (_, pos) if need_comma => { return Err(PERR::MissingToken( Token::Comma.into(), @@ -2342,7 +2344,7 @@ fn parse_block( // { ... { stmt } ??? (_, _) if !need_semicolon => (), // { ... stmt - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), // { ... stmt ??? (_, pos) => { // Semicolons are not optional between statements @@ -2960,7 +2962,7 @@ impl Engine { // { stmt } ??? (_, _) if !need_semicolon => (), // stmt - (Token::LexError(err), pos) => return Err(err.into_err(*pos)), + (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), // stmt ??? (_, pos) => { // Semicolons are not optional between statements diff --git a/src/result.rs b/src/result.rs index e9c5d224..7719f225 100644 --- a/src/result.rs +++ b/src/result.rs @@ -36,10 +36,10 @@ pub enum EvalAltResult { /// An error has occurred inside a called function. /// Wrapped values are the function name and the interior error. ErrorInFunctionCall(String, Box, Position), - /// Usage of an unknown module. Wrapped value is the module name. + /// Usage of an unknown [module][crate::Module]. Wrapped value is the [module][crate::Module] name. ErrorModuleNotFound(String, Position), - /// An error has occurred while loading a module. - /// Wrapped value are the module name and the interior error. + /// An error has occurred while loading a [module][crate::Module]. + /// Wrapped value are the [module][crate::Module] name and the interior error. ErrorInModule(String, Box, Position), /// Access to `this` that is not bound. ErrorUnboundThis(Position), @@ -72,7 +72,7 @@ pub enum EvalAltResult { ErrorArithmetic(String, Position), /// Number of operations over maximum limit. ErrorTooManyOperations(Position), - /// Modules over maximum limit. + /// [Modules][crate::Module] over maximum limit. ErrorTooManyModules(Position), /// Call stack over maximum limit. ErrorStackOverflow(Position), @@ -314,7 +314,7 @@ impl EvalAltResult { _ => false, } } - /// Get the [`Position`] of this error. + /// Get the [position][Position] of this error. pub fn position(&self) -> Position { match self { Self::ErrorSystem(_, _) => Position::NONE, @@ -347,7 +347,7 @@ impl EvalAltResult { | Self::Return(_, pos) => *pos, } } - /// Override the [`Position`] of this error. + /// Override the [position][Position] of this error. pub fn set_position(&mut self, new_position: Position) { match self { Self::ErrorSystem(_, _) => (), diff --git a/src/scope.rs b/src/scope.rs index c54ada9d..700a549f 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -30,7 +30,7 @@ impl EntryType { /// # Thread Safety /// /// Currently, [`Scope`] is neither [`Send`] nor [`Sync`]. -/// Turn on the [`Sync`] feature to make it [`Send`] `+` [`Sync`]. +/// Turn on the `sync` feature to make it [`Send`] `+` [`Sync`]. /// /// # Example /// diff --git a/src/syntax.rs b/src/syntax.rs index 695822e9..ce221146 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -61,7 +61,7 @@ impl Expression<'_> { } impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> { - /// Evaluate an expression tree. + /// Evaluate an [expression tree][Expression]. /// /// ## WARNING - Low Level API ///