rhai/eval/
global_state.rs1use crate::{expose_under_internals, Dynamic, Engine, ImmutableString};
4use std::fmt;
5#[cfg(feature = "no_std")]
6use std::prelude::v1::*;
7
8#[cfg(not(feature = "no_module"))]
10#[cfg(not(feature = "no_function"))]
11pub type SharedGlobalConstants =
12 crate::Shared<crate::Locked<std::collections::BTreeMap<ImmutableString, Dynamic>>>;
13
14#[derive(Clone)]
25pub struct GlobalRuntimeState {
26 #[cfg(not(feature = "no_module"))]
28 imports: crate::ThinVec<ImmutableString>,
29 #[cfg(not(feature = "no_module"))]
31 modules: crate::ThinVec<crate::SharedModule>,
32
33 #[cfg(not(feature = "no_function"))]
35 pub lib: crate::StaticVec<crate::SharedModule>,
36 pub source: Option<ImmutableString>,
40 pub num_operations: u64,
42 #[cfg(not(feature = "no_module"))]
44 pub num_modules_loaded: usize,
45 pub level: usize,
47 pub scope_level: usize,
51 pub always_search_scope: bool,
61 #[cfg(not(feature = "no_module"))]
63 pub embedded_module_resolver:
64 Option<crate::Shared<crate::module::resolvers::StaticModuleResolver>>,
65 #[cfg(not(feature = "no_module"))]
69 #[cfg(not(feature = "no_function"))]
70 pub constants: Option<SharedGlobalConstants>,
71 pub tag: Dynamic,
73 #[cfg(feature = "debugging")]
75 pub(crate) debugger: Option<Box<super::Debugger>>,
76}
77
78impl Engine {
79 #[expose_under_internals]
82 #[inline(always)]
83 #[must_use]
84 fn new_global_runtime_state(&self) -> GlobalRuntimeState {
85 GlobalRuntimeState {
86 #[cfg(not(feature = "no_module"))]
87 imports: crate::ThinVec::new(),
88 #[cfg(not(feature = "no_module"))]
89 modules: crate::ThinVec::new(),
90 #[cfg(not(feature = "no_function"))]
91 lib: crate::StaticVec::new(),
92 source: None,
93 num_operations: 0,
94 #[cfg(not(feature = "no_module"))]
95 num_modules_loaded: 0,
96 scope_level: 0,
97 level: 0,
98 always_search_scope: false,
99 #[cfg(not(feature = "no_module"))]
100 embedded_module_resolver: None,
101 #[cfg(not(feature = "no_module"))]
102 #[cfg(not(feature = "no_function"))]
103 constants: None,
104
105 tag: self.default_tag().clone(),
106
107 #[cfg(feature = "debugging")]
108 debugger: self.debugger_interface.as_ref().map(|x| {
109 let dbg = crate::eval::Debugger::new(crate::eval::DebuggerStatus::Init);
110 (x.0)(self, dbg).into()
111 }),
112 }
113 }
114}
115
116impl GlobalRuntimeState {
117 #[cfg(not(feature = "no_module"))]
121 #[inline(always)]
122 #[must_use]
123 pub fn num_imports(&self) -> usize {
124 self.modules.len()
125 }
126 #[cfg(not(feature = "no_module"))]
130 #[inline]
131 #[must_use]
132 pub fn get_shared_import(&self, index: usize) -> Option<crate::SharedModule> {
133 self.modules.get(index).cloned()
134 }
135 #[cfg(not(feature = "no_module"))]
139 #[inline]
140 #[must_use]
141 pub fn find_import(&self, name: &str) -> Option<usize> {
142 self.imports.iter().rposition(|key| key == name)
143 }
144 #[cfg(not(feature = "no_module"))]
148 #[inline]
149 pub fn push_import(
150 &mut self,
151 name: impl Into<ImmutableString>,
152 module: impl Into<crate::SharedModule>,
153 ) {
154 self.imports.push(name.into());
155
156 self.modules.push(module.into());
157 }
158 #[cfg(not(feature = "no_module"))]
162 #[inline(always)]
163 pub fn truncate_imports(&mut self, size: usize) {
164 self.imports.truncate(size);
165 self.modules.truncate(size);
166 }
167 #[cfg(not(feature = "no_module"))]
171 #[inline]
172 pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &crate::Module)> {
173 self.imports
174 .iter()
175 .rev()
176 .zip(self.modules.iter().rev())
177 .map(|(name, module)| (name.as_str(), &**module))
178 }
179 #[cfg(not(feature = "no_module"))]
183 #[inline]
184 pub fn iter_imports_raw(
185 &self,
186 ) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> {
187 self.imports.iter().rev().zip(self.modules.iter().rev())
188 }
189 #[cfg(not(feature = "no_module"))]
193 #[inline]
194 pub fn scan_imports_raw(
195 &self,
196 ) -> impl Iterator<Item = (&ImmutableString, &crate::SharedModule)> {
197 self.imports.iter().zip(self.modules.iter())
198 }
199 #[cfg(not(feature = "no_module"))]
204 #[inline]
205 pub(crate) fn may_contain_dynamic_fn(&self, hash_script: u64) -> bool {
206 self.modules
207 .iter()
208 .any(|m| m.may_contain_dynamic_fn(hash_script))
209 }
210 #[cfg(not(feature = "no_module"))]
215 #[allow(dead_code)]
216 #[inline]
217 #[must_use]
218 pub fn contains_qualified_fn(&self, hash: u64) -> bool {
219 self.modules.iter().any(|m| m.contains_qualified_fn(hash))
220 }
221 #[cfg(not(feature = "no_module"))]
226 #[inline]
227 #[must_use]
228 pub fn get_qualified_fn(
229 &self,
230 hash: u64,
231 global_namespace_only: bool,
232 ) -> Option<(&crate::func::RhaiFunc, Option<&ImmutableString>)> {
233 if global_namespace_only {
234 self.modules
235 .iter()
236 .rev()
237 .filter(|&m| m.contains_indexed_global_functions())
238 .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
239 } else {
240 self.modules
241 .iter()
242 .rev()
243 .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
244 }
245 }
246 #[cfg(not(feature = "no_module"))]
251 #[allow(dead_code)]
252 #[inline]
253 #[must_use]
254 pub fn contains_iter(&self, id: std::any::TypeId) -> bool {
255 self.modules.iter().any(|m| m.contains_qualified_iter(id))
256 }
257 #[cfg(not(feature = "no_module"))]
262 #[inline]
263 #[must_use]
264 pub fn get_iter(&self, id: std::any::TypeId) -> Option<&crate::func::FnIterator> {
265 self.modules
266 .iter()
267 .rev()
268 .find_map(|m| m.get_qualified_iter(id))
269 }
270 #[inline(always)]
272 #[must_use]
273 pub fn source(&self) -> Option<&str> {
274 self.source.as_deref()
275 }
276 #[inline(always)]
278 #[must_use]
279 #[allow(dead_code)]
280 pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
281 self.source.as_ref()
282 }
283
284 #[cfg(feature = "debugging")]
290 #[must_use]
291 pub fn debugger(&self) -> &super::Debugger {
292 self.debugger.as_ref().unwrap()
293 }
294 #[cfg(feature = "debugging")]
300 #[must_use]
301 pub fn debugger_mut(&mut self) -> &mut super::Debugger {
302 self.debugger.as_deref_mut().unwrap()
303 }
304}
305
306#[cfg(not(feature = "no_module"))]
307impl<K: Into<ImmutableString>, M: Into<crate::SharedModule>> Extend<(K, M)> for GlobalRuntimeState {
308 #[inline]
309 fn extend<T: IntoIterator<Item = (K, M)>>(&mut self, iter: T) {
310 for (k, m) in iter {
311 self.imports.push(k.into());
312 self.modules.push(m.into());
313 }
314 }
315}
316
317impl fmt::Debug for GlobalRuntimeState {
318 #[cold]
319 #[inline(never)]
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 let mut f = f.debug_struct("GlobalRuntimeState");
322
323 #[cfg(not(feature = "no_module"))]
324 f.field("imports", &self.scan_imports_raw().collect::<Vec<_>>())
325 .field("num_modules_loaded", &self.num_modules_loaded)
326 .field("embedded_module_resolver", &self.embedded_module_resolver);
327
328 #[cfg(not(feature = "no_function"))]
329 f.field("lib", &self.lib);
330
331 f.field("source", &self.source)
332 .field("num_operations", &self.num_operations)
333 .field("level", &self.level)
334 .field("scope_level", &self.scope_level)
335 .field("always_search_scope", &self.always_search_scope);
336
337 #[cfg(not(feature = "no_module"))]
338 #[cfg(not(feature = "no_function"))]
339 f.field("constants", &self.constants);
340
341 f.field("tag", &self.tag);
342
343 #[cfg(feature = "debugging")]
344 f.field("debugger", &self.debugger);
345
346 f.finish()
347 }
348}