Refine docs.
This commit is contained in:
parent
4add90b215
commit
01663a6581
@ -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.
|
||||
///
|
||||
/// # 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>> {
|
||||
/// 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(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Currently, `Engine` is neither `Send` nor `Sync`. Use the `sync` feature to make it `Send + Sync`.
|
||||
pub struct 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.
|
||||
pub(crate) global_module: Module,
|
||||
@ -541,9 +547,10 @@ pub struct Engine {
|
||||
impl fmt::Debug for Engine {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.id.as_ref() {
|
||||
Some(id) => write!(f, "Engine({})", id),
|
||||
None => f.write_str("Engine"),
|
||||
if !self.id.is_empty() {
|
||||
write!(f, "Engine({})", self.id)
|
||||
} else {
|
||||
f.write_str("Engine")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -645,7 +652,7 @@ impl Engine {
|
||||
pub fn new() -> Self {
|
||||
// Create the new scripting Engine
|
||||
let mut engine = Self {
|
||||
id: None,
|
||||
id: Default::default(),
|
||||
|
||||
packages: Default::default(),
|
||||
global_module: Default::default(),
|
||||
@ -707,7 +714,7 @@ impl Engine {
|
||||
#[inline(always)]
|
||||
pub fn new_raw() -> Self {
|
||||
Self {
|
||||
id: None,
|
||||
id: Default::default(),
|
||||
|
||||
packages: Default::default(),
|
||||
global_module: Default::default(),
|
||||
@ -2281,7 +2288,7 @@ impl Engine {
|
||||
|
||||
/// Make a Box<EvalAltResult<ErrorMismatchDataType>>.
|
||||
#[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(
|
||||
typ.into(),
|
||||
self.map_type_name(type_name::<T>()).into(),
|
||||
|
@ -387,9 +387,7 @@ impl Engine {
|
||||
let unified_lib = if let Some(ref env_lib) = fn_def.lib {
|
||||
lib_merged = Default::default();
|
||||
lib_merged.push(env_lib.as_ref());
|
||||
if !lib.is_empty() {
|
||||
lib_merged.extend(lib.iter().cloned());
|
||||
}
|
||||
lib_merged.as_ref()
|
||||
} else {
|
||||
lib
|
||||
@ -671,6 +669,11 @@ impl Engine {
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
self.inc_operations(state)?;
|
||||
|
||||
let script = script.trim();
|
||||
if script.is_empty() {
|
||||
return Ok(().into());
|
||||
}
|
||||
|
||||
// Check for stack overflow
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
@ -969,13 +972,9 @@ impl Engine {
|
||||
let var_name = var_name.as_str().map_err(|err| {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle is_def_fn()
|
||||
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())
|
||||
})?;
|
||||
|
||||
if fn_name.is_empty() || num_params < 0 {
|
||||
return Ok(false.into());
|
||||
return Ok(if num_params < 0 {
|
||||
false
|
||||
} else {
|
||||
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| {
|
||||
self.make_type_mismatch_err::<ImmutableString>(typ, args_expr[0].position())
|
||||
})?;
|
||||
let result = if !script.is_empty() {
|
||||
self.eval_script_expr(scope, mods, state, lib, script, level + 1)
|
||||
.map_err(|err| err.fill_position(args_expr[0].position()))
|
||||
} else {
|
||||
Ok(().into())
|
||||
};
|
||||
let result = self
|
||||
.eval_script_expr(scope, mods, state, lib, script, level + 1)
|
||||
.map_err(|err| err.fill_position(args_expr[0].position()));
|
||||
|
||||
// IMPORTANT! If the eval defines new variables in the current scope,
|
||||
// all variable offsets from this point on will be mis-aligned.
|
||||
|
@ -19,7 +19,7 @@ pub trait Func<ARGS, RET> {
|
||||
/// Create a Rust closure from an `AST`.
|
||||
/// The `Engine` and `AST` are consumed and basically embedded into the closure.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
@ -50,7 +50,7 @@ pub trait Func<ARGS, RET> {
|
||||
/// Create a Rust closure from a script.
|
||||
/// The `Engine` is consumed and basically embedded into the closure.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
|
@ -125,7 +125,7 @@ impl AsRef<Module> for Module {
|
||||
impl Module {
|
||||
/// Create a new module.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -141,7 +141,7 @@ impl Module {
|
||||
|
||||
/// Create a new module with a specified capacity for native Rust functions.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -160,7 +160,7 @@ impl Module {
|
||||
|
||||
/// Is the module empty?
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -199,7 +199,7 @@ impl Module {
|
||||
|
||||
/// Does a variable exist in the module?
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -215,7 +215,7 @@ impl Module {
|
||||
|
||||
/// Get the value of a module variable.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -231,7 +231,7 @@ impl Module {
|
||||
|
||||
/// Get a module variable as a `Dynamic`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -249,7 +249,7 @@ impl Module {
|
||||
///
|
||||
/// If there is an existing variable of the same name, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -327,7 +327,7 @@ impl Module {
|
||||
|
||||
/// Does a sub-module exist in the module?
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -344,7 +344,7 @@ impl Module {
|
||||
|
||||
/// Get a sub-module.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -361,7 +361,7 @@ impl Module {
|
||||
|
||||
/// Get a mutable reference to a sub-module.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -380,7 +380,7 @@ impl Module {
|
||||
///
|
||||
/// If there is an existing sub-module of the same name, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -402,7 +402,7 @@ impl Module {
|
||||
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
||||
/// It is also returned by the `set_fn_XXX` calls.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -500,7 +500,7 @@ impl Module {
|
||||
///
|
||||
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -555,7 +555,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -584,7 +584,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -615,7 +615,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -646,7 +646,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust getter function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Module;
|
||||
@ -669,7 +669,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -706,7 +706,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -743,7 +743,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing setter Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -775,7 +775,7 @@ impl Module {
|
||||
/// Panics if the type is `Array` or `Map`.
|
||||
/// Indexers for arrays, object maps and strings cannot be registered.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -813,7 +813,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -856,7 +856,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -904,7 +904,7 @@ impl Module {
|
||||
/// Panics if the type is `Array` or `Map`.
|
||||
/// Indexers for arrays, object maps and strings cannot be registered.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -962,7 +962,7 @@ impl Module {
|
||||
/// Panics if the type is `Array` or `Map`.
|
||||
/// Indexers for arrays, object maps and strings cannot be registered.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -997,7 +997,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -1047,7 +1047,7 @@ impl Module {
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
@ -1327,7 +1327,7 @@ impl Module {
|
||||
/// defined in the module, are _merged_ into a _unified_ namespace before each call.
|
||||
/// Therefore, all functions will be found.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
|
@ -8,7 +8,7 @@ use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
|
||||
/// Module resolution service that holds a collection of module resolves,
|
||||
/// to be searched in sequential order.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Engine, Module};
|
||||
@ -28,7 +28,7 @@ pub struct ModuleResolversCollection(Vec<Box<dyn ModuleResolver>>);
|
||||
impl ModuleResolversCollection {
|
||||
/// Create a new `ModuleResolversCollection`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Engine, Module};
|
||||
@ -80,10 +80,8 @@ impl ModuleResolversCollection {
|
||||
/// The other `ModuleResolversCollection` is consumed.
|
||||
#[inline(always)]
|
||||
pub fn append(&mut self, other: Self) {
|
||||
if !other.is_empty() {
|
||||
self.0.extend(other.0.into_iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleResolver for ModuleResolversCollection {
|
||||
|
@ -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
|
||||
/// the call. Therefore, functions in a module script can cross-call each other.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Engine;
|
||||
@ -53,7 +53,7 @@ impl Default for FileModuleResolver {
|
||||
impl FileModuleResolver {
|
||||
/// Create a new `FileModuleResolver` with a specific base path.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Engine;
|
||||
@ -75,7 +75,7 @@ impl FileModuleResolver {
|
||||
///
|
||||
/// The default extension is `.rhai`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Engine;
|
||||
@ -102,7 +102,7 @@ impl FileModuleResolver {
|
||||
|
||||
/// Create a new `FileModuleResolver` with the current directory as base path.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Engine;
|
||||
|
@ -7,7 +7,7 @@ use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::St
|
||||
|
||||
/// Module resolution service that serves modules added into it.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Engine, Module};
|
||||
@ -28,7 +28,7 @@ pub struct StaticModuleResolver(HashMap<String, Module>);
|
||||
impl StaticModuleResolver {
|
||||
/// Create a new `StaticModuleResolver`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Engine, Module};
|
||||
|
@ -798,7 +798,7 @@ fn optimize(
|
||||
|
||||
// Add back the last statement unless it is a lone No-op
|
||||
if let Some(stmt) = last_stmt {
|
||||
if !result.is_empty() || !matches!(stmt, Stmt::Noop(_)) {
|
||||
if !result.is_empty() || !stmt.is_noop() {
|
||||
result.push(stmt);
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ impl PackagesCollection {
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Dynamic, EvalAltResult};
|
||||
|
129
src/parser.rs
129
src/parser.rs
@ -74,6 +74,8 @@ type FunctionsLib = HashMap<u64, ScriptFnDef, StraightHasherBuilder>;
|
||||
|
||||
/// 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`.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct AST(
|
||||
@ -398,13 +400,8 @@ impl AST {
|
||||
mut filter: impl FnMut(FnAccess, &str, usize) -> bool,
|
||||
) -> &mut Self {
|
||||
let Self(ref mut statements, ref mut functions) = self;
|
||||
|
||||
if !other.0.is_empty() {
|
||||
statements.extend(other.0.into_iter());
|
||||
}
|
||||
|
||||
functions.merge_filtered(&other.1, &mut filter);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@ -798,55 +795,63 @@ impl Default for 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.
|
||||
pub fn position(&self) -> Position {
|
||||
match self {
|
||||
Stmt::Noop(pos) | Stmt::Continue(pos) | Stmt::Break(pos) => *pos,
|
||||
Stmt::Let(x) => (x.0).1,
|
||||
Stmt::Const(x) => (x.0).1,
|
||||
Stmt::Block(x) => x.1,
|
||||
Stmt::IfThenElse(x) => x.3,
|
||||
Stmt::Expr(x) => x.position(),
|
||||
Stmt::While(x) => x.2,
|
||||
Stmt::Loop(x) => x.1,
|
||||
Stmt::For(x) => x.3,
|
||||
Stmt::ReturnWithVal(x) => (x.0).1,
|
||||
Stmt::TryCatch(x) => (x.0).1,
|
||||
Self::Noop(pos) | Self::Continue(pos) | Self::Break(pos) => *pos,
|
||||
Self::Let(x) => (x.0).1,
|
||||
Self::Const(x) => (x.0).1,
|
||||
Self::Block(x) => x.1,
|
||||
Self::IfThenElse(x) => x.3,
|
||||
Self::Expr(x) => x.position(),
|
||||
Self::While(x) => x.2,
|
||||
Self::Loop(x) => x.1,
|
||||
Self::For(x) => x.3,
|
||||
Self::ReturnWithVal(x) => (x.0).1,
|
||||
Self::TryCatch(x) => (x.0).1,
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Import(x) => x.2,
|
||||
Self::Import(x) => x.2,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Export(x) => x.1,
|
||||
Self::Export(x) => x.1,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Stmt::Share(x) => x.1,
|
||||
Self::Share(x) => x.1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Override the `Position` of this statement.
|
||||
pub fn set_position(&mut self, new_pos: Position) -> &mut Self {
|
||||
match self {
|
||||
Stmt::Noop(pos) | Stmt::Continue(pos) | Stmt::Break(pos) => *pos = new_pos,
|
||||
Stmt::Let(x) => (x.0).1 = new_pos,
|
||||
Stmt::Const(x) => (x.0).1 = new_pos,
|
||||
Stmt::Block(x) => x.1 = new_pos,
|
||||
Stmt::IfThenElse(x) => x.3 = new_pos,
|
||||
Stmt::Expr(x) => {
|
||||
Self::Noop(pos) | Self::Continue(pos) | Self::Break(pos) => *pos = new_pos,
|
||||
Self::Let(x) => (x.0).1 = new_pos,
|
||||
Self::Const(x) => (x.0).1 = new_pos,
|
||||
Self::Block(x) => x.1 = new_pos,
|
||||
Self::IfThenElse(x) => x.3 = new_pos,
|
||||
Self::Expr(x) => {
|
||||
x.set_position(new_pos);
|
||||
}
|
||||
Stmt::While(x) => x.2 = new_pos,
|
||||
Stmt::Loop(x) => x.1 = new_pos,
|
||||
Stmt::For(x) => x.3 = new_pos,
|
||||
Stmt::ReturnWithVal(x) => (x.0).1 = new_pos,
|
||||
Stmt::TryCatch(x) => (x.0).1 = new_pos,
|
||||
Self::While(x) => x.2 = new_pos,
|
||||
Self::Loop(x) => x.1 = new_pos,
|
||||
Self::For(x) => x.3 = new_pos,
|
||||
Self::ReturnWithVal(x) => (x.0).1 = new_pos,
|
||||
Self::TryCatch(x) => (x.0).1 = new_pos,
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Import(x) => x.2 = new_pos,
|
||||
Self::Import(x) => x.2 = new_pos,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Export(x) => x.1 = new_pos,
|
||||
Self::Export(x) => x.1 = new_pos,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Stmt::Share(x) => x.1 = new_pos,
|
||||
Self::Share(x) => x.1 = new_pos,
|
||||
}
|
||||
|
||||
self
|
||||
@ -855,55 +860,55 @@ impl Stmt {
|
||||
/// Is this statement self-terminated (i.e. no need for a semicolon terminator)?
|
||||
pub fn is_self_terminated(&self) -> bool {
|
||||
match self {
|
||||
Stmt::IfThenElse(_)
|
||||
| Stmt::While(_)
|
||||
| Stmt::Loop(_)
|
||||
| Stmt::For(_)
|
||||
| Stmt::Block(_)
|
||||
| Stmt::TryCatch(_) => true,
|
||||
Self::IfThenElse(_)
|
||||
| Self::While(_)
|
||||
| Self::Loop(_)
|
||||
| Self::For(_)
|
||||
| Self::Block(_)
|
||||
| Self::TryCatch(_) => true,
|
||||
|
||||
// A No-op requires a semicolon in order to know it is an empty statement!
|
||||
Stmt::Noop(_) => false,
|
||||
Self::Noop(_) => false,
|
||||
|
||||
Stmt::Let(_)
|
||||
| Stmt::Const(_)
|
||||
| Stmt::Expr(_)
|
||||
| Stmt::Continue(_)
|
||||
| Stmt::Break(_)
|
||||
| Stmt::ReturnWithVal(_) => false,
|
||||
Self::Let(_)
|
||||
| Self::Const(_)
|
||||
| Self::Expr(_)
|
||||
| Self::Continue(_)
|
||||
| Self::Break(_)
|
||||
| Self::ReturnWithVal(_) => false,
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Import(_) | Stmt::Export(_) => false,
|
||||
Self::Import(_) | Self::Export(_) => false,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Stmt::Share(_) => false,
|
||||
Self::Share(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this statement _pure_?
|
||||
pub fn is_pure(&self) -> bool {
|
||||
match self {
|
||||
Stmt::Noop(_) => true,
|
||||
Stmt::Expr(expr) => expr.is_pure(),
|
||||
Stmt::IfThenElse(x) if x.2.is_some() => {
|
||||
Self::Noop(_) => true,
|
||||
Self::Expr(expr) => expr.is_pure(),
|
||||
Self::IfThenElse(x) if x.2.is_some() => {
|
||||
x.0.is_pure() && x.1.is_pure() && x.2.as_ref().unwrap().is_pure()
|
||||
}
|
||||
Stmt::IfThenElse(x) => x.1.is_pure(),
|
||||
Stmt::While(x) => x.0.is_pure() && x.1.is_pure(),
|
||||
Stmt::Loop(x) => x.0.is_pure(),
|
||||
Stmt::For(x) => x.1.is_pure() && x.2.is_pure(),
|
||||
Stmt::Let(_) | Stmt::Const(_) => false,
|
||||
Stmt::Block(x) => x.0.iter().all(Stmt::is_pure),
|
||||
Stmt::Continue(_) | Stmt::Break(_) | Stmt::ReturnWithVal(_) => false,
|
||||
Stmt::TryCatch(x) => (x.0).0.is_pure() && (x.2).0.is_pure(),
|
||||
Self::IfThenElse(x) => x.1.is_pure(),
|
||||
Self::While(x) => x.0.is_pure() && x.1.is_pure(),
|
||||
Self::Loop(x) => x.0.is_pure(),
|
||||
Self::For(x) => x.1.is_pure() && x.2.is_pure(),
|
||||
Self::Let(_) | Self::Const(_) => false,
|
||||
Self::Block(x) => x.0.iter().all(Self::is_pure),
|
||||
Self::Continue(_) | Self::Break(_) | Self::ReturnWithVal(_) => false,
|
||||
Self::TryCatch(x) => (x.0).0.is_pure() && (x.2).0.is_pure(),
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Import(_) => false,
|
||||
Self::Import(_) => false,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Export(_) => false,
|
||||
Self::Export(_) => false,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Stmt::Share(_) => false,
|
||||
Self::Share(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ use crate::stdlib::{
|
||||
///
|
||||
/// 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`.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
|
32
src/scope.rs
32
src/scope.rs
@ -44,6 +44,10 @@ pub struct Entry<'a> {
|
||||
/// Type containing information about the current scope.
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
@ -67,15 +71,13 @@ pub struct Entry<'a> {
|
||||
///
|
||||
/// When searching for entries, newly-added entries are found before similarly-named but older entries,
|
||||
/// 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)]
|
||||
pub struct Scope<'a>(Vec<Entry<'a>>);
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
/// Create a new Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -92,7 +94,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Empty the Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -117,7 +119,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Get the number of entries inside the Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -135,7 +137,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Is the Scope empty?
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -153,7 +155,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Add (push) a new entry to the Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -174,7 +176,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Add (push) a new `Dynamic` entry to the Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// 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:
|
||||
/// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -225,7 +227,7 @@ impl<'a> Scope<'a> {
|
||||
/// recognized types:
|
||||
/// `INT` (default to `i64`, `i32` if `only_i32`), `f64`, `String`, `char` and `bool`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Dynamic, Scope};
|
||||
@ -272,7 +274,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Truncate (rewind) the Scope to a previous size.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -304,7 +306,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Does the scope contain the entry?
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -350,7 +352,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Get the value of an entry in the Scope, starting from the last.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -374,7 +376,7 @@ impl<'a> Scope<'a> {
|
||||
///
|
||||
/// Panics when trying to update the value of a constant.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::Scope;
|
||||
@ -450,7 +452,7 @@ impl<'a> Scope<'a> {
|
||||
|
||||
/// Get an iterator to entries in the Scope.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Dynamic, Scope};
|
||||
|
@ -70,7 +70,7 @@ impl<'de> DynamicDeserializer<'de> {
|
||||
|
||||
/// Deserialize a `Dynamic` value into a Rust type that implements `serde::Deserialize`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
|
@ -46,7 +46,7 @@ impl DynamicSerializer {
|
||||
|
||||
/// Serialize a Rust type that implements `serde::Serialize` into a `Dynamic`.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
|
@ -248,7 +248,7 @@ impl Engine {
|
||||
///
|
||||
/// The operator must be a valid identifier (i.e. it cannot be a symbol).
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
|
@ -96,7 +96,7 @@ pub fn calc_fn_hash<'a>(
|
||||
/// An `ImmutableString` wraps an `Rc<String>` (or `Arc<String>` under the `sync` feature)
|
||||
/// so that it can be simply shared and not cloned.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::ImmutableString;
|
||||
|
@ -84,7 +84,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
|
||||
"hello",
|
||||
|stream| match stream.len() {
|
||||
0 => unreachable!(),
|
||||
1 => Ok(Some("$ident$".into())),
|
||||
1 => Ok(Some("$ident$".to_string())),
|
||||
2 => match stream[1].as_str() {
|
||||
"world" | "kitty" => Ok(None),
|
||||
s => Err(ParseError(
|
||||
|
Loading…
Reference in New Issue
Block a user