diff --git a/Cargo.toml b/Cargo.toml index a5177aa6..4ed917d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ no_stdlib = [] # no standard library of utility functions no_index = [] # no arrays and indexing no_float = [] # no floating-point no_function = [] # no script-defined functions +no_optimize = [] # no script optimizer only_i32 = [] # set INT=i32 (useful for 32-bit systems) only_i64 = [] # set INT=i64 (default) and disable support for all other integer types diff --git a/README.md b/README.md index db33e369..b5870ee1 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ Optional features | `no_function` | Disable script-defined functions if you don't need them. | | `no_index` | Disable arrays and indexing features if you don't need them. | | `no_float` | Disable floating-point numbers and math if you don't need them. | +| `no_optimize` | Disable the script optimizer. | | `only_i32` | Set the system integer type to `i32` and disable all other integer types. | | `only_i64` | Set the system integer type to `i64` and disable all other integer types. | @@ -1099,6 +1100,7 @@ Optimizations ============= Rhai includes an _optimizer_ that tries to optimize a script after parsing. This can reduce resource utilization and increase execution speed. +Script optimization can be turned off via the [`no_optimize`] feature. For example, in the following: @@ -1228,6 +1230,7 @@ engine.set_optimization(false); // turn off the optimizer [`no_index`]: #optional-features [`no_float`]: #optional-features [`no_function`]: #optional-features +[`no_optimize`]: #optional-features [`only_i32`]: #optional-features [`only_i64`]: #optional-features diff --git a/src/parser.rs b/src/parser.rs index e660d0c6..daebaf13 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,9 +2,11 @@ use crate::any::Dynamic; use crate::error::{LexError, ParseError, ParseErrorType}; -use crate::optimize::optimize; use crate::scope::{Scope, VariableType}; +#[cfg(not(feature = "no_optimize"))] +use crate::optimize::optimize; + use std::{ borrow::Cow, char, cmp::Ordering, fmt, iter::Peekable, str::Chars, str::FromStr, sync::Arc, usize, @@ -23,6 +25,7 @@ pub type INT = i64; pub type INT = i32; /// The system floating-point type +#[cfg(not(feature = "no_float"))] pub type FLOAT = f64; type LERR = LexError; @@ -161,6 +164,7 @@ impl AST { /// constant values. The script AST can be compiled just once. During actual evaluation, /// constants are passed into the Engine via an external scope (i.e. with `scope.push_constant(...)`). /// Then, the AST is cloned and the copy re-optimized before running. + #[cfg(not(feature = "no_optimize"))] pub fn optimize(self, scope: &Scope) -> Self { AST( crate::optimize::optimize(self.0, scope), @@ -2140,25 +2144,34 @@ fn parse_top_level<'a>( } } - return Ok(AST( - if optimize_ast { - optimize(statements, &scope) - } else { - statements - }, - #[cfg(not(feature = "no_function"))] - functions - .into_iter() - .map(|mut fn_def| { - if optimize_ast { - let pos = fn_def.body.position(); - let mut body = optimize(vec![fn_def.body], &scope); - fn_def.body = body.pop().unwrap_or_else(|| Stmt::Noop(pos)); - } - Arc::new(fn_def) - }) - .collect(), - )); + Ok( + #[cfg(not(feature = "no_optimize"))] + AST( + if optimize_ast { + optimize(statements, &scope) + } else { + statements + }, + #[cfg(not(feature = "no_function"))] + functions + .into_iter() + .map(|mut fn_def| { + if optimize_ast { + let pos = fn_def.body.position(); + let mut body = optimize(vec![fn_def.body], &scope); + fn_def.body = body.pop().unwrap_or_else(|| Stmt::Noop(pos)); + } + Arc::new(fn_def) + }) + .collect(), + ), + #[cfg(feature = "no_optimize")] + AST( + statements, + #[cfg(not(feature = "no_function"))] + functions.into_iter().map(Arc::new).collect(), + ), + ) } pub fn parse<'a>(