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}