Restructure code base.
This commit is contained in:
179
src/api/deprecated.rs
Normal file
179
src/api/deprecated.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
//! Module containing all deprecated API that will be removed in the next major version.
|
||||
|
||||
use crate::{
|
||||
Dynamic, Engine, EvalAltResult, ImmutableString, NativeCallContext, RhaiResult, Scope, AST,
|
||||
};
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
impl Engine {
|
||||
/// Evaluate a file, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// Not available under `no_std` or `WASM`.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run_file`][Engine::run_file] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run_file` instead")]
|
||||
#[cfg(not(feature = "no_std"))]
|
||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||
#[inline(always)]
|
||||
pub fn consume_file(&self, path: std::path::PathBuf) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run_file(path)
|
||||
}
|
||||
|
||||
/// Evaluate a file with own scope, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// Not available under `no_std` or `WASM`.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run_file_with_scope`][Engine::run_file_with_scope] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run_file_with_scope` instead")]
|
||||
#[cfg(not(feature = "no_std"))]
|
||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||
#[inline(always)]
|
||||
pub fn consume_file_with_scope(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
path: std::path::PathBuf,
|
||||
) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run_file_with_scope(scope, path)
|
||||
}
|
||||
|
||||
/// Evaluate a string, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run`][Engine::run] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run` instead")]
|
||||
#[inline(always)]
|
||||
pub fn consume(&self, script: &str) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run(script)
|
||||
}
|
||||
|
||||
/// Evaluate a string with own scope, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run_with_scope`][Engine::run_with_scope] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run_with_scope` instead")]
|
||||
#[inline(always)]
|
||||
pub fn consume_with_scope(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
script: &str,
|
||||
) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run_with_scope(scope, script)
|
||||
}
|
||||
|
||||
/// Evaluate an AST, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run_ast`][Engine::run_ast] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run_ast` instead")]
|
||||
#[inline(always)]
|
||||
pub fn consume_ast(&self, ast: &AST) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run_ast(ast)
|
||||
}
|
||||
|
||||
/// Evaluate an [`AST`] with own scope, but throw away the result and only return error (if any).
|
||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`run_ast_with_scope`][Engine::run_ast_with_scope] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `run_ast_with_scope` instead")]
|
||||
#[inline(always)]
|
||||
pub fn consume_ast_with_scope(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
ast: &AST,
|
||||
) -> Result<(), Box<EvalAltResult>> {
|
||||
self.run_ast_with_scope(scope, ast)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dynamic {
|
||||
/// Convert the [`Dynamic`] into a [`String`] and return it.
|
||||
/// If there are other references to the same string, a cloned copy is returned.
|
||||
/// Returns the name of the actual type if the cast fails.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`into_string`][Dynamic::into_string] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `into_string` instead")]
|
||||
#[inline(always)]
|
||||
pub fn as_string(self) -> Result<String, &'static str> {
|
||||
self.into_string()
|
||||
}
|
||||
|
||||
/// Convert the [`Dynamic`] into an [`ImmutableString`] and return it.
|
||||
/// Returns the name of the actual type if the cast fails.
|
||||
///
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This method is deprecated. Use [`into_immutable_string`][Dynamic::into_immutable_string] instead.
|
||||
///
|
||||
/// This method will be removed in the next major version.
|
||||
#[deprecated(since = "1.1.0", note = "use `into_immutable_string` instead")]
|
||||
#[inline(always)]
|
||||
pub fn as_immutable_string(self) -> Result<ImmutableString, &'static str> {
|
||||
self.into_immutable_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeCallContext<'_> {
|
||||
/// Call a function inside the call context.
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// All arguments may be _consumed_, meaning that they may be replaced by `()`.
|
||||
/// This is to avoid unnecessarily cloning the arguments.
|
||||
///
|
||||
/// Do not use the arguments after this call. If they are needed afterwards,
|
||||
/// clone them _before_ calling this function.
|
||||
///
|
||||
/// If `is_method` is [`true`], the first argument is assumed to be passed
|
||||
/// by reference and is not consumed.
|
||||
#[deprecated(since = "1.2.0", note = "use `call_fn_raw` instead")]
|
||||
#[inline(always)]
|
||||
pub fn call_fn_dynamic_raw(
|
||||
&self,
|
||||
fn_name: impl AsRef<str>,
|
||||
is_method_call: bool,
|
||||
args: &mut [&mut Dynamic],
|
||||
) -> RhaiResult {
|
||||
self.call_fn_raw(fn_name.as_ref(), is_method_call, is_method_call, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(useless_deprecated)]
|
||||
#[deprecated(since = "1.2.0", note = "explicitly wrap `EvalAltResult` in `Err`")]
|
||||
impl<T> From<EvalAltResult> for Result<T, Box<EvalAltResult>> {
|
||||
#[inline(always)]
|
||||
fn from(err: EvalAltResult) -> Self {
|
||||
Err(err.into())
|
||||
}
|
||||
}
|
5
src/api/mod.rs
Normal file
5
src/api/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
//! Module defining the public API of the Rhai engine.
|
||||
|
||||
pub mod deprecated;
|
||||
pub mod public;
|
||||
pub mod settings;
|
2372
src/api/public.rs
Normal file
2372
src/api/public.rs
Normal file
File diff suppressed because it is too large
Load Diff
334
src/api/settings.rs
Normal file
334
src/api/settings.rs
Normal file
@@ -0,0 +1,334 @@
|
||||
//! Configuration settings for [`Engine`].
|
||||
|
||||
use crate::tokenizer::Token;
|
||||
use crate::Engine;
|
||||
use crate::{engine::Precedence, Identifier};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
use std::num::{NonZeroU64, NonZeroUsize};
|
||||
|
||||
impl Engine {
|
||||
/// Control whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
||||
///
|
||||
/// Not available under `no_optimize`.
|
||||
#[cfg(not(feature = "no_optimize"))]
|
||||
#[inline(always)]
|
||||
pub fn set_optimization_level(
|
||||
&mut self,
|
||||
optimization_level: crate::OptimizationLevel,
|
||||
) -> &mut Self {
|
||||
self.optimization_level = optimization_level;
|
||||
self
|
||||
}
|
||||
/// The current optimization level.
|
||||
/// It controls whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
||||
///
|
||||
/// Not available under `no_optimize`.
|
||||
#[cfg(not(feature = "no_optimize"))]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn optimization_level(&self) -> crate::OptimizationLevel {
|
||||
self.optimization_level
|
||||
}
|
||||
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
||||
/// infinite recursion and stack overflows.
|
||||
///
|
||||
/// Not available under `unchecked` or `no_function`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_call_levels(&mut self, levels: usize) -> &mut Self {
|
||||
self.limits.max_call_stack_depth = levels;
|
||||
self
|
||||
}
|
||||
/// The maximum levels of function calls allowed for a script.
|
||||
///
|
||||
/// Not available under `unchecked` or `no_function`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_call_levels(&self) -> usize {
|
||||
self.limits.max_call_stack_depth
|
||||
}
|
||||
/// Set the maximum number of operations allowed for a script to run to avoid
|
||||
/// consuming too much resources (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_operations(&mut self, operations: u64) -> &mut Self {
|
||||
self.limits.max_operations = NonZeroU64::new(operations);
|
||||
self
|
||||
}
|
||||
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_operations(&self) -> u64 {
|
||||
if let Some(n) = self.limits.max_operations {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
||||
///
|
||||
/// Not available under `unchecked` or `no_module`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_modules(&mut self, modules: usize) -> &mut Self {
|
||||
self.limits.max_modules = modules;
|
||||
self
|
||||
}
|
||||
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
||||
///
|
||||
/// Not available under `unchecked` or `no_module`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_modules(&self) -> usize {
|
||||
self.limits.max_modules
|
||||
}
|
||||
/// Set the depth limits for expressions (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_expr_depths(
|
||||
&mut self,
|
||||
max_expr_depth: usize,
|
||||
#[cfg(not(feature = "no_function"))] max_function_expr_depth: usize,
|
||||
) -> &mut Self {
|
||||
self.limits.max_expr_depth = NonZeroUsize::new(max_expr_depth);
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
{
|
||||
self.limits.max_function_expr_depth = NonZeroUsize::new(max_function_expr_depth);
|
||||
}
|
||||
self
|
||||
}
|
||||
/// The depth limit for expressions (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_expr_depth(&self) -> usize {
|
||||
if let Some(n) = self.limits.max_expr_depth {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// The depth limit for expressions in functions (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked` or `no_function`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_function_expr_depth(&self) -> usize {
|
||||
if let Some(n) = self.limits.max_function_expr_depth {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self {
|
||||
self.limits.max_string_size = NonZeroUsize::new(max_size);
|
||||
self
|
||||
}
|
||||
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_string_size(&self) -> usize {
|
||||
if let Some(n) = self.limits.max_string_size {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked` or `no_index`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self {
|
||||
self.limits.max_array_size = NonZeroUsize::new(max_size);
|
||||
self
|
||||
}
|
||||
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked` or `no_index`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_array_size(&self) -> usize {
|
||||
if let Some(n) = self.limits.max_array_size {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Set the maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked` or `no_object`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline(always)]
|
||||
pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self {
|
||||
self.limits.max_map_size = NonZeroUsize::new(max_size);
|
||||
self
|
||||
}
|
||||
/// The maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||
///
|
||||
/// Not available under `unchecked` or `no_object`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_map_size(&self) -> usize {
|
||||
if let Some(n) = self.limits.max_map_size {
|
||||
n.get()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
/// Set the module resolution service used by the [`Engine`].
|
||||
///
|
||||
/// Not available under `no_module`.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline(always)]
|
||||
pub fn set_module_resolver(
|
||||
&mut self,
|
||||
resolver: impl crate::ModuleResolver + 'static,
|
||||
) -> &mut Self {
|
||||
self.module_resolver = Some(Box::new(resolver));
|
||||
self
|
||||
}
|
||||
/// Disable a particular keyword or operator in the language.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following will raise an error during parsing because the `if` keyword is disabled
|
||||
/// and is recognized as a reserved symbol!
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// # fn main() -> Result<(), rhai::ParseError> {
|
||||
/// use rhai::Engine;
|
||||
///
|
||||
/// let mut engine = Engine::new();
|
||||
///
|
||||
/// engine.disable_symbol("if"); // disable the 'if' keyword
|
||||
///
|
||||
/// engine.compile("let x = if true { 42 } else { 0 };")?;
|
||||
/// // ^ 'if' is rejected as a reserved symbol
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The following will raise an error during parsing because the `+=` operator is disabled.
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// # fn main() -> Result<(), rhai::ParseError> {
|
||||
/// use rhai::Engine;
|
||||
///
|
||||
/// let mut engine = Engine::new();
|
||||
///
|
||||
/// engine.disable_symbol("+="); // disable the '+=' operator
|
||||
///
|
||||
/// engine.compile("let x = 42; x += 1;")?;
|
||||
/// // ^ unknown operator
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn disable_symbol(&mut self, symbol: impl Into<Identifier>) -> &mut Self {
|
||||
self.disabled_symbols.insert(symbol.into());
|
||||
self
|
||||
}
|
||||
/// Register a custom operator with a precedence into the language.
|
||||
///
|
||||
/// The operator must be a valid identifier (i.e. it cannot be a symbol).
|
||||
///
|
||||
/// The precedence cannot be zero.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
/// use rhai::Engine;
|
||||
///
|
||||
/// let mut engine = Engine::new();
|
||||
///
|
||||
/// // Register a custom operator called 'foo' and give it
|
||||
/// // a precedence of 160 (i.e. between +|- and *|/).
|
||||
/// engine.register_custom_operator("foo", 160).expect("should succeed");
|
||||
///
|
||||
/// // Register a binary function named 'foo'
|
||||
/// engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// engine.eval_expression::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?,
|
||||
/// 15
|
||||
/// );
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn register_custom_operator(
|
||||
&mut self,
|
||||
keyword: impl AsRef<str> + Into<Identifier>,
|
||||
precedence: u8,
|
||||
) -> Result<&mut Self, String> {
|
||||
let precedence = Precedence::new(precedence);
|
||||
|
||||
if precedence.is_none() {
|
||||
return Err("precedence cannot be zero".into());
|
||||
}
|
||||
|
||||
match Token::lookup_from_syntax(keyword.as_ref()) {
|
||||
// Standard identifiers, reserved keywords and custom keywords are OK
|
||||
None | Some(Token::Reserved(_)) | Some(Token::Custom(_)) => (),
|
||||
// Active standard keywords cannot be made custom
|
||||
// Disabled keywords are OK
|
||||
Some(token) if token.is_standard_keyword() => {
|
||||
if !self.disabled_symbols.contains(&*token.syntax()) {
|
||||
return Err(format!("'{}' is a reserved keyword", keyword.as_ref()));
|
||||
}
|
||||
}
|
||||
// Active standard symbols cannot be made custom
|
||||
Some(token) if token.is_standard_symbol() => {
|
||||
if !self.disabled_symbols.contains(&*token.syntax()) {
|
||||
return Err(format!("'{}' is a reserved operator", keyword.as_ref()));
|
||||
}
|
||||
}
|
||||
// Active standard symbols cannot be made custom
|
||||
Some(token) if !self.disabled_symbols.contains(&*token.syntax()) => {
|
||||
return Err(format!("'{}' is a reserved symbol", keyword.as_ref()))
|
||||
}
|
||||
// Disabled symbols are OK
|
||||
Some(_) => (),
|
||||
}
|
||||
|
||||
// Add to custom keywords
|
||||
self.custom_keywords.insert(keyword.into(), precedence);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user