Skip to main content

rhai/api/
run.rs

1//! Module that defines the public evaluation API of [`Engine`].
2
3use crate::tokenizer::TokenStream;
4use crate::eval::Caches;
5use crate::parser::ParseState;
6use crate::{Engine, RhaiResultOf, Scope, AST};
7#[cfg(feature = "no_std")]
8use std::prelude::v1::*;
9
10impl Engine {
11    /// Evaluate a string as a script.
12    ///
13    /// # Example
14    ///
15    /// ```
16    /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
17    /// use rhai::Engine;
18    ///
19    /// let engine = Engine::new();
20    ///
21    /// engine.run("print(40 + 2);")?;
22    /// # Ok(())
23    /// # }
24    /// ```
25    #[inline(always)]
26    pub fn run(&self, script: &str) -> RhaiResultOf<()> {
27        self.run_with_scope(&mut Scope::new(), script)
28    }
29    /// Evaluate a string as a script with own scope.
30    ///
31    /// ## Constants Propagation
32    ///
33    /// If not [`OptimizationLevel::None`][crate::OptimizationLevel::None], constants defined within
34    /// the scope are propagated throughout the script _including_ functions.
35    ///
36    /// This allows functions to be optimized based on dynamic global constants.
37    ///
38    /// # Example
39    ///
40    /// ```
41    /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
42    /// use rhai::{Engine, Scope};
43    ///
44    /// let engine = Engine::new();
45    ///
46    /// // Create initialized scope
47    /// let mut scope = Scope::new();
48    /// scope.push("x", 40_i64);
49    ///
50    /// engine.run_with_scope(&mut scope, "x += 2; print(x);")?;
51    ///
52    /// // The variable in the scope is modified
53    /// assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 42);
54    /// # Ok(())
55    /// # }
56    /// ```
57    #[inline]
58    pub fn run_with_scope(&self, scope: &mut Scope, script: &str) -> RhaiResultOf<()> {
59        let scripts = [script];
60        let ast = {
61            let (stream, tc) = self.lex(&scripts);
62
63            let input = &mut TokenStream::new(stream);
64            let lib = &mut <_>::default();
65            let state = ParseState::new(Some(scope), input, tc, lib);
66
67            self.parse(
68                state,
69                #[cfg(not(feature = "no_optimize"))]
70                self.optimization_level,
71            )?
72        };
73        self.run_ast_with_scope(scope, &ast)
74    }
75    /// Evaluate an [`AST`].
76    ///
77    /// # Example
78    ///
79    /// ```
80    /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
81    /// use rhai::Engine;
82    ///
83    /// let engine = Engine::new();
84    ///
85    /// // Compile a script to an AST and store it for later evaluation
86    /// let ast = engine.compile("print(40 + 2);")?;
87    ///
88    /// // Evaluate it
89    /// engine.run_ast(&ast)?;
90    /// # Ok(())
91    /// # }
92    /// ```
93    #[inline(always)]
94    pub fn run_ast(&self, ast: &AST) -> RhaiResultOf<()> {
95        self.run_ast_with_scope(&mut Scope::new(), ast)
96    }
97    /// Evaluate an [`AST`] with own scope.
98    ///
99    /// # Example
100    ///
101    /// ```
102    /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
103    /// use rhai::{Engine, Scope};
104    ///
105    /// let engine = Engine::new();
106    ///
107    /// // Create initialized scope
108    /// let mut scope = Scope::new();
109    /// scope.push("x", 40_i64);
110    ///
111    /// // Compile a script to an AST and store it for later evaluation
112    /// let ast = engine.compile("x += 2; x")?;
113    ///
114    /// // Evaluate it
115    /// engine.run_ast_with_scope(&mut scope, &ast)?;
116    ///
117    /// // The variable in the scope is modified
118    /// assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 42);
119    /// # Ok(())
120    /// # }
121    /// ```
122    #[inline]
123    pub fn run_ast_with_scope(&self, scope: &mut Scope, ast: &AST) -> RhaiResultOf<()> {
124        let caches = &mut Caches::new();
125        let global = &mut self.new_global_runtime_state();
126        global.source = ast.source_raw().cloned();
127
128        #[cfg(not(feature = "no_function"))]
129        global.lib.push(ast.shared_lib().clone());
130
131        #[cfg(not(feature = "no_module"))]
132        global.embedded_module_resolver.clone_from(&ast.resolver);
133
134        let _ = self.eval_global_statements(global, caches, scope, ast.statements(), true)?;
135
136        #[cfg(feature = "debugging")]
137        if self.is_debugger_registered() {
138            global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
139            let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
140            self.dbg(global, caches, scope, None, node)?;
141        }
142
143        Ok(())
144    }
145}
146
147/// Evaluate a string as a script.
148///
149/// # Example
150///
151/// ```
152/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
153/// rhai::run("print(40 + 2);")?;
154/// # Ok(())
155/// # }
156/// ```
157#[inline(always)]
158pub fn run(script: &str) -> RhaiResultOf<()> {
159    Engine::new().run(script)
160}