Refine docs.

This commit is contained in:
Stephen Chung 2020-10-27 11:30:38 +08:00
parent 4add90b215
commit 01663a6581
17 changed files with 163 additions and 152 deletions

View File

@ -484,6 +484,14 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm,
/// Rhai main scripting engine. /// Rhai main scripting engine.
/// ///
/// # Thread Safety
///
/// `Engine` is re-entrant.
///
/// Currently, `Engine` is neither `Send` nor `Sync`. Use the `sync` feature to make it `Send + Sync`.
///
/// # Example
///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine; /// use rhai::Engine;
@ -496,11 +504,9 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm,
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
///
/// Currently, `Engine` is neither `Send` nor `Sync`. Use the `sync` feature to make it `Send + Sync`.
pub struct Engine { pub struct Engine {
/// A unique ID identifying this scripting `Engine`. /// A unique ID identifying this scripting `Engine`.
pub id: Option<String>, pub id: String,
/// A module containing all functions directly loaded into the Engine. /// A module containing all functions directly loaded into the Engine.
pub(crate) global_module: Module, pub(crate) global_module: Module,
@ -541,9 +547,10 @@ pub struct Engine {
impl fmt::Debug for Engine { impl fmt::Debug for Engine {
#[inline(always)] #[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.id.as_ref() { if !self.id.is_empty() {
Some(id) => write!(f, "Engine({})", id), write!(f, "Engine({})", self.id)
None => f.write_str("Engine"), } else {
f.write_str("Engine")
} }
} }
} }
@ -645,7 +652,7 @@ impl Engine {
pub fn new() -> Self { pub fn new() -> Self {
// Create the new scripting Engine // Create the new scripting Engine
let mut engine = Self { let mut engine = Self {
id: None, id: Default::default(),
packages: Default::default(), packages: Default::default(),
global_module: Default::default(), global_module: Default::default(),
@ -707,7 +714,7 @@ impl Engine {
#[inline(always)] #[inline(always)]
pub fn new_raw() -> Self { pub fn new_raw() -> Self {
Self { Self {
id: None, id: Default::default(),
packages: Default::default(), packages: Default::default(),
global_module: Default::default(), global_module: Default::default(),
@ -2281,7 +2288,7 @@ impl Engine {
/// Make a Box<EvalAltResult<ErrorMismatchDataType>>. /// Make a Box<EvalAltResult<ErrorMismatchDataType>>.
#[inline(always)] #[inline(always)]
pub fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> Box<EvalAltResult> { pub(crate) fn make_type_mismatch_err<T>(&self, typ: &str, pos: Position) -> Box<EvalAltResult> {
EvalAltResult::ErrorMismatchDataType( EvalAltResult::ErrorMismatchDataType(
typ.into(), typ.into(),
self.map_type_name(type_name::<T>()).into(), self.map_type_name(type_name::<T>()).into(),

View File

@ -387,9 +387,7 @@ impl Engine {
let unified_lib = if let Some(ref env_lib) = fn_def.lib { let unified_lib = if let Some(ref env_lib) = fn_def.lib {
lib_merged = Default::default(); lib_merged = Default::default();
lib_merged.push(env_lib.as_ref()); lib_merged.push(env_lib.as_ref());
if !lib.is_empty() {
lib_merged.extend(lib.iter().cloned()); lib_merged.extend(lib.iter().cloned());
}
lib_merged.as_ref() lib_merged.as_ref()
} else { } else {
lib lib
@ -671,6 +669,11 @@ impl Engine {
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
self.inc_operations(state)?; self.inc_operations(state)?;
let script = script.trim();
if script.is_empty() {
return Ok(().into());
}
// Check for stack overflow // Check for stack overflow
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
@ -969,13 +972,9 @@ impl Engine {
let var_name = var_name.as_str().map_err(|err| { let var_name = var_name.as_str().map_err(|err| {
self.make_type_mismatch_err::<ImmutableString>(err, args_expr[0].position()) self.make_type_mismatch_err::<ImmutableString>(err, args_expr[0].position())
})?; })?;
if var_name.is_empty() {
return Ok(false.into());
} else {
return Ok(scope.contains(var_name).into()); return Ok(scope.contains(var_name).into());
} }
} }
}
// Handle is_def_fn() // Handle is_def_fn()
if name == KEYWORD_IS_DEF_FN && args_expr.len() == 2 { if name == KEYWORD_IS_DEF_FN && args_expr.len() == 2 {
@ -1001,12 +1000,13 @@ impl Engine {
self.make_type_mismatch_err::<INT>(err, args_expr[1].position()) self.make_type_mismatch_err::<INT>(err, args_expr[1].position())
})?; })?;
if fn_name.is_empty() || num_params < 0 { return Ok(if num_params < 0 {
return Ok(false.into()); false
} else { } else {
let hash = calc_fn_hash(empty(), fn_name, num_params as usize, empty()); let hash = calc_fn_hash(empty(), fn_name, num_params as usize, empty());
return Ok(lib.iter().any(|&m| m.contains_fn(hash, false)).into()); lib.iter().any(|&m| m.contains_fn(hash, false))
} }
.into());
} }
} }
@ -1022,12 +1022,9 @@ impl Engine {
let script = script.as_str().map_err(|typ| { let script = script.as_str().map_err(|typ| {
self.make_type_mismatch_err::<ImmutableString>(typ, args_expr[0].position()) self.make_type_mismatch_err::<ImmutableString>(typ, args_expr[0].position())
})?; })?;
let result = if !script.is_empty() { let result = self
self.eval_script_expr(scope, mods, state, lib, script, level + 1) .eval_script_expr(scope, mods, state, lib, script, level + 1)
.map_err(|err| err.fill_position(args_expr[0].position())) .map_err(|err| err.fill_position(args_expr[0].position()));
} else {
Ok(().into())
};
// IMPORTANT! If the eval defines new variables in the current scope, // IMPORTANT! If the eval defines new variables in the current scope,
// all variable offsets from this point on will be mis-aligned. // all variable offsets from this point on will be mis-aligned.

View File

@ -19,7 +19,7 @@ pub trait Func<ARGS, RET> {
/// Create a Rust closure from an `AST`. /// Create a Rust closure from an `AST`.
/// The `Engine` and `AST` are consumed and basically embedded into the closure. /// The `Engine` and `AST` are consumed and basically embedded into the closure.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
@ -50,7 +50,7 @@ pub trait Func<ARGS, RET> {
/// Create a Rust closure from a script. /// Create a Rust closure from a script.
/// The `Engine` is consumed and basically embedded into the closure. /// The `Engine` is consumed and basically embedded into the closure.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {

View File

@ -125,7 +125,7 @@ impl AsRef<Module> for Module {
impl Module { impl Module {
/// Create a new module. /// Create a new module.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -141,7 +141,7 @@ impl Module {
/// Create a new module with a specified capacity for native Rust functions. /// Create a new module with a specified capacity for native Rust functions.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -160,7 +160,7 @@ impl Module {
/// Is the module empty? /// Is the module empty?
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -199,7 +199,7 @@ impl Module {
/// Does a variable exist in the module? /// Does a variable exist in the module?
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -215,7 +215,7 @@ impl Module {
/// Get the value of a module variable. /// Get the value of a module variable.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -231,7 +231,7 @@ impl Module {
/// Get a module variable as a `Dynamic`. /// Get a module variable as a `Dynamic`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -249,7 +249,7 @@ impl Module {
/// ///
/// If there is an existing variable of the same name, it is replaced. /// If there is an existing variable of the same name, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -327,7 +327,7 @@ impl Module {
/// Does a sub-module exist in the module? /// Does a sub-module exist in the module?
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -344,7 +344,7 @@ impl Module {
/// Get a sub-module. /// Get a sub-module.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -361,7 +361,7 @@ impl Module {
/// Get a mutable reference to a sub-module. /// Get a mutable reference to a sub-module.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -380,7 +380,7 @@ impl Module {
/// ///
/// If there is an existing sub-module of the same name, it is replaced. /// If there is an existing sub-module of the same name, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -402,7 +402,7 @@ impl Module {
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`. /// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
/// It is also returned by the `set_fn_XXX` calls. /// It is also returned by the `set_fn_XXX` calls.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -500,7 +500,7 @@ impl Module {
/// ///
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()` /// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -555,7 +555,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -584,7 +584,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -615,7 +615,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -646,7 +646,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust getter function, it is replaced. /// If there is a similar existing Rust getter function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Module; /// use rhai::Module;
@ -669,7 +669,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -706,7 +706,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -743,7 +743,7 @@ impl Module {
/// ///
/// If there is a similar existing setter Rust function, it is replaced. /// If there is a similar existing setter Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -775,7 +775,7 @@ impl Module {
/// Panics if the type is `Array` or `Map`. /// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered. /// Indexers for arrays, object maps and strings cannot be registered.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -813,7 +813,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -856,7 +856,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -904,7 +904,7 @@ impl Module {
/// Panics if the type is `Array` or `Map`. /// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered. /// Indexers for arrays, object maps and strings cannot be registered.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -962,7 +962,7 @@ impl Module {
/// Panics if the type is `Array` or `Map`. /// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered. /// Indexers for arrays, object maps and strings cannot be registered.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -997,7 +997,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -1047,7 +1047,7 @@ impl Module {
/// ///
/// If there is a similar existing Rust function, it is replaced. /// If there is a similar existing Rust function, it is replaced.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Module, ImmutableString}; /// use rhai::{Module, ImmutableString};
@ -1327,7 +1327,7 @@ impl Module {
/// defined in the module, are _merged_ into a _unified_ namespace before each call. /// defined in the module, are _merged_ into a _unified_ namespace before each call.
/// Therefore, all functions will be found. /// Therefore, all functions will be found.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {

View File

@ -8,7 +8,7 @@ use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
/// Module resolution service that holds a collection of module resolves, /// Module resolution service that holds a collection of module resolves,
/// to be searched in sequential order. /// to be searched in sequential order.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Engine, Module}; /// use rhai::{Engine, Module};
@ -28,7 +28,7 @@ pub struct ModuleResolversCollection(Vec<Box<dyn ModuleResolver>>);
impl ModuleResolversCollection { impl ModuleResolversCollection {
/// Create a new `ModuleResolversCollection`. /// Create a new `ModuleResolversCollection`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Engine, Module}; /// use rhai::{Engine, Module};
@ -80,10 +80,8 @@ impl ModuleResolversCollection {
/// The other `ModuleResolversCollection` is consumed. /// The other `ModuleResolversCollection` is consumed.
#[inline(always)] #[inline(always)]
pub fn append(&mut self, other: Self) { pub fn append(&mut self, other: Self) {
if !other.is_empty() {
self.0.extend(other.0.into_iter()); self.0.extend(other.0.into_iter());
} }
}
} }
impl ModuleResolver for ModuleResolversCollection { impl ModuleResolver for ModuleResolversCollection {

View File

@ -22,7 +22,7 @@ use crate::stdlib::{boxed::Box, collections::HashMap, path::PathBuf, string::Str
/// plus all those defined within the same module are _merged_ into a _unified_ namespace before /// plus all those defined within the same module are _merged_ into a _unified_ namespace before
/// the call. Therefore, functions in a module script can cross-call each other. /// the call. Therefore, functions in a module script can cross-call each other.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Engine; /// use rhai::Engine;
@ -53,7 +53,7 @@ impl Default for FileModuleResolver {
impl FileModuleResolver { impl FileModuleResolver {
/// Create a new `FileModuleResolver` with a specific base path. /// Create a new `FileModuleResolver` with a specific base path.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Engine; /// use rhai::Engine;
@ -75,7 +75,7 @@ impl FileModuleResolver {
/// ///
/// The default extension is `.rhai`. /// The default extension is `.rhai`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Engine; /// use rhai::Engine;
@ -102,7 +102,7 @@ impl FileModuleResolver {
/// Create a new `FileModuleResolver` with the current directory as base path. /// Create a new `FileModuleResolver` with the current directory as base path.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Engine; /// use rhai::Engine;

View File

@ -7,7 +7,7 @@ use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::St
/// Module resolution service that serves modules added into it. /// Module resolution service that serves modules added into it.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Engine, Module}; /// use rhai::{Engine, Module};
@ -28,7 +28,7 @@ pub struct StaticModuleResolver(HashMap<String, Module>);
impl StaticModuleResolver { impl StaticModuleResolver {
/// Create a new `StaticModuleResolver`. /// Create a new `StaticModuleResolver`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Engine, Module}; /// use rhai::{Engine, Module};

View File

@ -798,7 +798,7 @@ fn optimize(
// Add back the last statement unless it is a lone No-op // Add back the last statement unless it is a lone No-op
if let Some(stmt) = last_stmt { if let Some(stmt) = last_stmt {
if !result.is_empty() || !matches!(stmt, Stmt::Noop(_)) { if !result.is_empty() || !stmt.is_noop() {
result.push(stmt); result.push(stmt);
} }
} }

View File

@ -94,7 +94,7 @@ impl PackagesCollection {
/// Functions can be added to the package using the standard module methods such as /// Functions can be added to the package using the standard module methods such as
/// `set_fn_2`, `set_fn_3_mut`, `set_fn_0` etc. /// `set_fn_2`, `set_fn_3_mut`, `set_fn_0` etc.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Dynamic, EvalAltResult}; /// use rhai::{Dynamic, EvalAltResult};

View File

@ -74,6 +74,8 @@ type FunctionsLib = HashMap<u64, ScriptFnDef, StraightHasherBuilder>;
/// Compiled AST (abstract syntax tree) of a Rhai script. /// Compiled AST (abstract syntax tree) of a Rhai script.
/// ///
/// # Thread Safety
///
/// Currently, `AST` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`. /// Currently, `AST` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct AST( pub struct AST(
@ -398,13 +400,8 @@ impl AST {
mut filter: impl FnMut(FnAccess, &str, usize) -> bool, mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
) -> &mut Self { ) -> &mut Self {
let Self(ref mut statements, ref mut functions) = self; let Self(ref mut statements, ref mut functions) = self;
if !other.0.is_empty() {
statements.extend(other.0.into_iter()); statements.extend(other.0.into_iter());
}
functions.merge_filtered(&other.1, &mut filter); functions.merge_filtered(&other.1, &mut filter);
self self
} }
@ -798,55 +795,63 @@ impl Default for Stmt {
} }
impl Stmt { impl Stmt {
/// Is this statement `Noop`?
pub fn is_noop(&self) -> bool {
match self {
Self::Noop(_) => true,
_ => false,
}
}
/// Get the `Position` of this statement. /// Get the `Position` of this statement.
pub fn position(&self) -> Position { pub fn position(&self) -> Position {
match self { match self {
Stmt::Noop(pos) | Stmt::Continue(pos) | Stmt::Break(pos) => *pos, Self::Noop(pos) | Self::Continue(pos) | Self::Break(pos) => *pos,
Stmt::Let(x) => (x.0).1, Self::Let(x) => (x.0).1,
Stmt::Const(x) => (x.0).1, Self::Const(x) => (x.0).1,
Stmt::Block(x) => x.1, Self::Block(x) => x.1,
Stmt::IfThenElse(x) => x.3, Self::IfThenElse(x) => x.3,
Stmt::Expr(x) => x.position(), Self::Expr(x) => x.position(),
Stmt::While(x) => x.2, Self::While(x) => x.2,
Stmt::Loop(x) => x.1, Self::Loop(x) => x.1,
Stmt::For(x) => x.3, Self::For(x) => x.3,
Stmt::ReturnWithVal(x) => (x.0).1, Self::ReturnWithVal(x) => (x.0).1,
Stmt::TryCatch(x) => (x.0).1, Self::TryCatch(x) => (x.0).1,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(x) => x.2, Self::Import(x) => x.2,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Export(x) => x.1, Self::Export(x) => x.1,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => x.1, Self::Share(x) => x.1,
} }
} }
/// Override the `Position` of this statement. /// Override the `Position` of this statement.
pub fn set_position(&mut self, new_pos: Position) -> &mut Self { pub fn set_position(&mut self, new_pos: Position) -> &mut Self {
match self { match self {
Stmt::Noop(pos) | Stmt::Continue(pos) | Stmt::Break(pos) => *pos = new_pos, Self::Noop(pos) | Self::Continue(pos) | Self::Break(pos) => *pos = new_pos,
Stmt::Let(x) => (x.0).1 = new_pos, Self::Let(x) => (x.0).1 = new_pos,
Stmt::Const(x) => (x.0).1 = new_pos, Self::Const(x) => (x.0).1 = new_pos,
Stmt::Block(x) => x.1 = new_pos, Self::Block(x) => x.1 = new_pos,
Stmt::IfThenElse(x) => x.3 = new_pos, Self::IfThenElse(x) => x.3 = new_pos,
Stmt::Expr(x) => { Self::Expr(x) => {
x.set_position(new_pos); x.set_position(new_pos);
} }
Stmt::While(x) => x.2 = new_pos, Self::While(x) => x.2 = new_pos,
Stmt::Loop(x) => x.1 = new_pos, Self::Loop(x) => x.1 = new_pos,
Stmt::For(x) => x.3 = new_pos, Self::For(x) => x.3 = new_pos,
Stmt::ReturnWithVal(x) => (x.0).1 = new_pos, Self::ReturnWithVal(x) => (x.0).1 = new_pos,
Stmt::TryCatch(x) => (x.0).1 = new_pos, Self::TryCatch(x) => (x.0).1 = new_pos,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(x) => x.2 = new_pos, Self::Import(x) => x.2 = new_pos,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Export(x) => x.1 = new_pos, Self::Export(x) => x.1 = new_pos,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => x.1 = new_pos, Self::Share(x) => x.1 = new_pos,
} }
self self
@ -855,55 +860,55 @@ impl Stmt {
/// Is this statement self-terminated (i.e. no need for a semicolon terminator)? /// Is this statement self-terminated (i.e. no need for a semicolon terminator)?
pub fn is_self_terminated(&self) -> bool { pub fn is_self_terminated(&self) -> bool {
match self { match self {
Stmt::IfThenElse(_) Self::IfThenElse(_)
| Stmt::While(_) | Self::While(_)
| Stmt::Loop(_) | Self::Loop(_)
| Stmt::For(_) | Self::For(_)
| Stmt::Block(_) | Self::Block(_)
| Stmt::TryCatch(_) => true, | Self::TryCatch(_) => true,
// A No-op requires a semicolon in order to know it is an empty statement! // A No-op requires a semicolon in order to know it is an empty statement!
Stmt::Noop(_) => false, Self::Noop(_) => false,
Stmt::Let(_) Self::Let(_)
| Stmt::Const(_) | Self::Const(_)
| Stmt::Expr(_) | Self::Expr(_)
| Stmt::Continue(_) | Self::Continue(_)
| Stmt::Break(_) | Self::Break(_)
| Stmt::ReturnWithVal(_) => false, | Self::ReturnWithVal(_) => false,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(_) | Stmt::Export(_) => false, Self::Import(_) | Self::Export(_) => false,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(_) => false, Self::Share(_) => false,
} }
} }
/// Is this statement _pure_? /// Is this statement _pure_?
pub fn is_pure(&self) -> bool { pub fn is_pure(&self) -> bool {
match self { match self {
Stmt::Noop(_) => true, Self::Noop(_) => true,
Stmt::Expr(expr) => expr.is_pure(), Self::Expr(expr) => expr.is_pure(),
Stmt::IfThenElse(x) if x.2.is_some() => { Self::IfThenElse(x) if x.2.is_some() => {
x.0.is_pure() && x.1.is_pure() && x.2.as_ref().unwrap().is_pure() x.0.is_pure() && x.1.is_pure() && x.2.as_ref().unwrap().is_pure()
} }
Stmt::IfThenElse(x) => x.1.is_pure(), Self::IfThenElse(x) => x.1.is_pure(),
Stmt::While(x) => x.0.is_pure() && x.1.is_pure(), Self::While(x) => x.0.is_pure() && x.1.is_pure(),
Stmt::Loop(x) => x.0.is_pure(), Self::Loop(x) => x.0.is_pure(),
Stmt::For(x) => x.1.is_pure() && x.2.is_pure(), Self::For(x) => x.1.is_pure() && x.2.is_pure(),
Stmt::Let(_) | Stmt::Const(_) => false, Self::Let(_) | Self::Const(_) => false,
Stmt::Block(x) => x.0.iter().all(Stmt::is_pure), Self::Block(x) => x.0.iter().all(Self::is_pure),
Stmt::Continue(_) | Stmt::Break(_) | Stmt::ReturnWithVal(_) => false, Self::Continue(_) | Self::Break(_) | Self::ReturnWithVal(_) => false,
Stmt::TryCatch(x) => (x.0).0.is_pure() && (x.2).0.is_pure(), Self::TryCatch(x) => (x.0).0.is_pure() && (x.2).0.is_pure(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(_) => false, Self::Import(_) => false,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Export(_) => false, Self::Export(_) => false,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(_) => false, Self::Share(_) => false,
} }
} }
} }

View File

@ -20,6 +20,8 @@ use crate::stdlib::{
/// ///
/// All wrapped `Position` values represent the location in the script where the error occurs. /// All wrapped `Position` values represent the location in the script where the error occurs.
/// ///
/// # Thread Safety
///
/// Currently, `EvalAltResult` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`. /// Currently, `EvalAltResult` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive] #[non_exhaustive]

View File

@ -44,6 +44,10 @@ pub struct Entry<'a> {
/// Type containing information about the current scope. /// Type containing information about the current scope.
/// Useful for keeping state between `Engine` evaluation runs. /// Useful for keeping state between `Engine` evaluation runs.
/// ///
/// # Thread Safety
///
/// Currently, `Scope` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -67,15 +71,13 @@ pub struct Entry<'a> {
/// ///
/// When searching for entries, newly-added entries are found before similarly-named but older entries, /// When searching for entries, newly-added entries are found before similarly-named but older entries,
/// allowing for automatic _shadowing_. /// allowing for automatic _shadowing_.
///
/// Currently, `Scope` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct Scope<'a>(Vec<Entry<'a>>); pub struct Scope<'a>(Vec<Entry<'a>>);
impl<'a> Scope<'a> { impl<'a> Scope<'a> {
/// Create a new Scope. /// Create a new Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -92,7 +94,7 @@ impl<'a> Scope<'a> {
/// Empty the Scope. /// Empty the Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -117,7 +119,7 @@ impl<'a> Scope<'a> {
/// Get the number of entries inside the Scope. /// Get the number of entries inside the Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -135,7 +137,7 @@ impl<'a> Scope<'a> {
/// Is the Scope empty? /// Is the Scope empty?
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -153,7 +155,7 @@ impl<'a> Scope<'a> {
/// Add (push) a new entry to the Scope. /// Add (push) a new entry to the Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -174,7 +176,7 @@ impl<'a> Scope<'a> {
/// Add (push) a new `Dynamic` entry to the Scope. /// Add (push) a new `Dynamic` entry to the Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Dynamic, Scope}; /// use rhai::{Dynamic, Scope};
@ -197,7 +199,7 @@ impl<'a> Scope<'a> {
/// However, in order to be used for optimization, constants must be in one of the recognized types: /// However, in order to be used for optimization, constants must be in one of the recognized types:
/// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`. /// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -225,7 +227,7 @@ impl<'a> Scope<'a> {
/// recognized types: /// recognized types:
/// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`. /// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Dynamic, Scope}; /// use rhai::{Dynamic, Scope};
@ -272,7 +274,7 @@ impl<'a> Scope<'a> {
/// Truncate (rewind) the Scope to a previous size. /// Truncate (rewind) the Scope to a previous size.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -304,7 +306,7 @@ impl<'a> Scope<'a> {
/// Does the scope contain the entry? /// Does the scope contain the entry?
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -350,7 +352,7 @@ impl<'a> Scope<'a> {
/// Get the value of an entry in the Scope, starting from the last. /// Get the value of an entry in the Scope, starting from the last.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -374,7 +376,7 @@ impl<'a> Scope<'a> {
/// ///
/// Panics when trying to update the value of a constant. /// Panics when trying to update the value of a constant.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::Scope; /// use rhai::Scope;
@ -450,7 +452,7 @@ impl<'a> Scope<'a> {
/// Get an iterator to entries in the Scope. /// Get an iterator to entries in the Scope.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::{Dynamic, Scope}; /// use rhai::{Dynamic, Scope};

View File

@ -70,7 +70,7 @@ impl<'de> DynamicDeserializer<'de> {
/// Deserialize a `Dynamic` value into a Rust type that implements `serde::Deserialize`. /// Deserialize a `Dynamic` value into a Rust type that implements `serde::Deserialize`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {

View File

@ -46,7 +46,7 @@ impl DynamicSerializer {
/// Serialize a Rust type that implements `serde::Serialize` into a `Dynamic`. /// Serialize a Rust type that implements `serde::Serialize` into a `Dynamic`.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {

View File

@ -248,7 +248,7 @@ impl Engine {
/// ///
/// The operator must be a valid identifier (i.e. it cannot be a symbol). /// The operator must be a valid identifier (i.e. it cannot be a symbol).
/// ///
/// # Examples /// # Example
/// ///
/// ```rust /// ```rust
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {

View File

@ -96,7 +96,7 @@ pub fn calc_fn_hash<'a>(
/// An `ImmutableString` wraps an `Rc<String>` (or `Arc<String>` under the `sync` feature) /// An `ImmutableString` wraps an `Rc<String>` (or `Arc<String>` under the `sync` feature)
/// so that it can be simply shared and not cloned. /// so that it can be simply shared and not cloned.
/// ///
/// # Examples /// # Example
/// ///
/// ``` /// ```
/// use rhai::ImmutableString; /// use rhai::ImmutableString;

View File

@ -84,7 +84,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
"hello", "hello",
|stream| match stream.len() { |stream| match stream.len() {
0 => unreachable!(), 0 => unreachable!(),
1 => Ok(Some("$ident$".into())), 1 => Ok(Some("$ident$".to_string())),
2 => match stream[1].as_str() { 2 => match stream[1].as_str() {
"world" | "kitty" => Ok(None), "world" | "kitty" => Ok(None),
s => Err(ParseError( s => Err(ParseError(