Rename Imports to GlobalRuntimeState.

This commit is contained in:
Stephen Chung
2021-12-28 11:42:52 +08:00
parent 9deddc679c
commit 807240e249
9 changed files with 112 additions and 84 deletions

View File

@@ -695,48 +695,6 @@ impl Engine {
})
}
/// Evaluate a text script in place - used primarily for 'eval'.
fn eval_script_expr_in_place(
&self,
scope: &mut Scope,
global: &mut GlobalRuntimeState,
lib: &[&Module],
script: impl AsRef<str>,
_pos: Position,
level: usize,
) -> RhaiResult {
#[cfg(not(feature = "unchecked"))]
self.inc_operations(&mut global.num_operations, _pos)?;
let script = script.as_ref().trim();
if script.is_empty() {
return Ok(Dynamic::UNIT);
}
// Compile the script text
// No optimizations because we only run it once
let ast = self.compile_with_scope_and_optimization_level(
&Scope::new(),
&[script],
#[cfg(not(feature = "no_optimize"))]
crate::OptimizationLevel::None,
)?;
// If new functions are defined within the eval string, it is an error
#[cfg(not(feature = "no_function"))]
if !ast.shared_lib().is_empty() {
return Err(crate::PERR::WrongFnDefinition.into());
}
let statements = ast.statements();
if statements.is_empty() {
return Ok(Dynamic::UNIT);
}
// Evaluate the AST
self.eval_global_statements(scope, global, &mut EvalState::new(), statements, lib, level)
}
/// Call a dot method.
#[cfg(not(feature = "no_object"))]
pub(crate) fn make_method_call(
@@ -1081,13 +1039,14 @@ impl Engine {
let script = &value
.into_immutable_string()
.map_err(|typ| self.make_type_mismatch_err::<ImmutableString>(typ, pos))?;
let level = level + 1;
let result =
self.eval_script_expr_in_place(scope, global, lib, script, pos, level + 1);
self.eval_script_expr_in_place(scope, global, state, lib, script, pos, level);
// IMPORTANT! If the eval defines new variables in the current scope,
// all variable offsets from this point on will be mis-aligned.
if scope.len() != orig_scope_len {
state.always_search_scope = true;
state.data.always_search_scope = true;
}
return result.map_err(|err| {

View File

@@ -186,7 +186,8 @@ impl<'a> NativeCallContext<'a> {
pub const fn source(&self) -> Option<&str> {
self.source
}
/// Get an iterator over the current set of modules imported via `import` statements.
/// Get an iterator over the current set of modules imported via `import` statements
/// in reverse order.
///
/// Not available under `no_module`.
#[cfg(not(feature = "no_module"))]
@@ -194,7 +195,7 @@ impl<'a> NativeCallContext<'a> {
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
self.global.iter().flat_map(|&m| m.iter_modules())
}
/// Get an iterator over the current set of modules imported via `import` statements.
/// Get an iterator over the current set of modules imported via `import` statements in reverse order.
#[cfg(not(feature = "no_module"))]
#[allow(dead_code)]
#[inline]
@@ -214,10 +215,11 @@ impl<'a> NativeCallContext<'a> {
pub const fn global_runtime_state(&self) -> Option<&GlobalRuntimeState> {
self.global
}
/// Get an iterator over the namespaces containing definitions of all script-defined functions.
/// Get an iterator over the namespaces containing definitions of all script-defined functions
/// in reverse order.
#[inline]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned()
self.lib.iter().rev().cloned()
}
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
/// Exported under the `internals` feature only.

View File

@@ -3,7 +3,7 @@
use super::call::FnCallArgs;
use crate::ast::ScriptFnDef;
use crate::engine::{EvalState, GlobalRuntimeState};
use crate::engine::{EvalState, EvalStateData, GlobalRuntimeState};
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::{Dynamic, Engine, Module, Position, RhaiError, RhaiResult, Scope, StaticVec, ERR};
use std::mem;
@@ -91,6 +91,8 @@ impl Engine {
// Merge in encapsulated environment, if any
let mut lib_merged = StaticVec::with_capacity(lib.len() + 1);
let orig_fn_resolution_caches_len = state.fn_resolution_caches_len();
let orig_states_data = state.data;
state.data = EvalStateData::new();
let lib = if let Some(ref fn_lib) = fn_def.lib {
if fn_lib.is_empty() {
@@ -106,15 +108,14 @@ impl Engine {
};
#[cfg(not(feature = "no_module"))]
if fn_def.global.num_imported_modules() > 0 {
fn_def
.global
.iter_modules_raw()
.for_each(|(n, m)| global.push_module(n.clone(), m.clone()));
if let Some(ref modules) = fn_def.global {
modules
.iter()
.cloned()
.for_each(|(n, m)| global.push_module(n, m));
}
// Evaluate the function
let body = &fn_def.body;
let result = self
.eval_stmt_block(
scope,
@@ -122,7 +123,7 @@ impl Engine {
state,
lib,
this_ptr,
body,
&fn_def.body,
true,
rewind_scope,
level,
@@ -149,15 +150,17 @@ impl Engine {
_ => make_error(fn_def.name.to_string(), fn_def, global, err, pos),
});
// Remove all local variables
// Remove all local variables and imported modules
if rewind_scope {
scope.rewind(orig_scope_len);
} else if !args.is_empty() {
// Remove arguments only, leaving new variables in the scope
scope.remove_range(orig_scope_len, args.len())
}
global.truncate_modules(orig_mods_len);
// Restore state
state.data = orig_states_data;
state.rewind_fn_resolution_caches(orig_fn_resolution_caches_len);
result
@@ -193,4 +196,47 @@ impl Engine {
result
}
/// Evaluate a text script in place - used primarily for 'eval'.
pub(crate) fn eval_script_expr_in_place(
&self,
scope: &mut Scope,
global: &mut GlobalRuntimeState,
state: &mut EvalState,
lib: &[&Module],
script: impl AsRef<str>,
_pos: Position,
level: usize,
) -> RhaiResult {
#[cfg(not(feature = "unchecked"))]
self.inc_operations(&mut global.num_operations, _pos)?;
let script = script.as_ref().trim();
if script.is_empty() {
return Ok(Dynamic::UNIT);
}
// Compile the script text
// No optimizations because we only run it once
let ast = self.compile_with_scope_and_optimization_level(
&Scope::new(),
&[script],
#[cfg(not(feature = "no_optimize"))]
crate::OptimizationLevel::None,
)?;
// If new functions are defined within the eval string, it is an error
#[cfg(not(feature = "no_function"))]
if !ast.shared_lib().is_empty() {
return Err(crate::PERR::WrongFnDefinition.into());
}
let statements = ast.statements();
if statements.is_empty() {
return Ok(Dynamic::UNIT);
}
// Evaluate the AST
self.eval_global_statements(scope, global, state, statements, lib, level)
}
}