Move encapsulated environment out of ScriptFnDef.
This commit is contained in:
@@ -644,9 +644,10 @@ impl Engine {
|
||||
// Script function call
|
||||
assert!(func.is_script());
|
||||
|
||||
let func = func.get_script_fn_def().expect("script-defined function");
|
||||
let f = func.get_script_fn_def().expect("script-defined function");
|
||||
let environ = func.get_encapsulated_environ();
|
||||
|
||||
if func.body.is_empty() {
|
||||
if f.body.is_empty() {
|
||||
return Ok((Dynamic::UNIT, false));
|
||||
}
|
||||
|
||||
@@ -666,7 +667,7 @@ impl Engine {
|
||||
let (first_arg, rest_args) = _args.split_first_mut().unwrap();
|
||||
|
||||
self.call_script_fn(
|
||||
global, caches, scope, first_arg, func, rest_args, true, pos,
|
||||
global, caches, scope, first_arg, environ, f, rest_args, true, pos,
|
||||
)
|
||||
} else {
|
||||
// Normal call of script function
|
||||
@@ -683,7 +684,17 @@ impl Engine {
|
||||
|
||||
let mut this_ptr = Dynamic::NULL;
|
||||
|
||||
self.call_script_fn(global, caches, scope, &mut this_ptr, func, args, true, pos)
|
||||
self.call_script_fn(
|
||||
global,
|
||||
caches,
|
||||
scope,
|
||||
&mut this_ptr,
|
||||
environ,
|
||||
f,
|
||||
args,
|
||||
true,
|
||||
pos,
|
||||
)
|
||||
}
|
||||
.map(|r| (r, false));
|
||||
}
|
||||
@@ -770,6 +781,7 @@ impl Engine {
|
||||
caches,
|
||||
&mut Scope::new(),
|
||||
&mut this_ptr,
|
||||
None,
|
||||
fn_def,
|
||||
args,
|
||||
true,
|
||||
@@ -856,6 +868,7 @@ impl Engine {
|
||||
caches,
|
||||
&mut Scope::new(),
|
||||
target,
|
||||
None,
|
||||
&fn_def,
|
||||
args,
|
||||
true,
|
||||
@@ -1064,6 +1077,7 @@ impl Engine {
|
||||
caches,
|
||||
&mut Scope::new(),
|
||||
&mut this_ptr,
|
||||
None,
|
||||
&fn_def,
|
||||
args,
|
||||
true,
|
||||
@@ -1441,15 +1455,27 @@ impl Engine {
|
||||
|
||||
match func {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Some(f) if f.is_script() => {
|
||||
let f = f.get_script_fn_def().expect("script-defined function");
|
||||
Some(func) if func.is_script() => {
|
||||
let f = func.get_script_fn_def().expect("script-defined function");
|
||||
let environ = func.get_encapsulated_environ();
|
||||
|
||||
let scope = &mut Scope::new();
|
||||
let mut this_ptr = Dynamic::NULL;
|
||||
|
||||
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
||||
auto_restore!(global => move |g| g.source = orig_source);
|
||||
|
||||
self.call_script_fn(global, caches, scope, &mut this_ptr, f, args, true, pos)
|
||||
self.call_script_fn(
|
||||
global,
|
||||
caches,
|
||||
scope,
|
||||
&mut this_ptr,
|
||||
environ,
|
||||
f,
|
||||
args,
|
||||
true,
|
||||
pos,
|
||||
)
|
||||
}
|
||||
|
||||
Some(f) if f.is_plugin_fn() => {
|
||||
|
@@ -8,6 +8,26 @@ use std::fmt;
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
/// _(internals)_ Encapsulated AST environment.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// 1) functions defined within the same AST
|
||||
/// 2) the stack of imported [modules][crate::Module]
|
||||
/// 3) global constants
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EncapsulatedEnviron {
|
||||
/// Functions defined within the same [`AST`][crate::AST].
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub lib: crate::SharedModule,
|
||||
/// Imported [modules][crate::Module].
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
pub imports: Box<[(crate::ImmutableString, crate::SharedModule)]>,
|
||||
/// Globally-defined constants.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub constants: Option<crate::eval::SharedGlobalConstants>,
|
||||
}
|
||||
|
||||
/// _(internals)_ A type encapsulating a function callable by Rhai.
|
||||
/// Exported under the `internals` feature only.
|
||||
#[derive(Clone)]
|
||||
@@ -24,7 +44,10 @@ pub enum CallableFunction {
|
||||
Plugin(Shared<FnPlugin>),
|
||||
/// A script-defined function.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Script(Shared<crate::ast::ScriptFnDef>),
|
||||
Script(
|
||||
Shared<crate::ast::ScriptFnDef>,
|
||||
Option<Shared<EncapsulatedEnviron>>,
|
||||
),
|
||||
}
|
||||
|
||||
impl fmt::Debug for CallableFunction {
|
||||
@@ -38,7 +61,7 @@ impl fmt::Debug for CallableFunction {
|
||||
Self::Plugin(..) => f.write_str("PluginFunction"),
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Self::Script(fn_def) => fmt::Debug::fmt(fn_def, f),
|
||||
Self::Script(fn_def, ..) => fmt::Debug::fmt(fn_def, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +75,7 @@ impl fmt::Display for CallableFunction {
|
||||
Self::Plugin(..) => f.write_str("PluginFunction"),
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Self::Script(s) => fmt::Display::fmt(s, f),
|
||||
Self::Script(fn_def, ..) => fmt::Display::fmt(fn_def, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +183,7 @@ impl CallableFunction {
|
||||
Self::Plugin(..) | Self::Pure(..) | Self::Method(..) | Self::Iterator(..) => {
|
||||
FnAccess::Public
|
||||
}
|
||||
Self::Script(f) => f.access,
|
||||
Self::Script(f, ..) => f.access,
|
||||
}
|
||||
}
|
||||
/// Get a shared reference to a native Rust function.
|
||||
@@ -184,7 +207,20 @@ impl CallableFunction {
|
||||
pub const fn get_script_fn_def(&self) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
||||
match self {
|
||||
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) | Self::Plugin(..) => None,
|
||||
Self::Script(f) => Some(f),
|
||||
Self::Script(f, ..) => Some(f),
|
||||
}
|
||||
}
|
||||
/// Get a reference to the shared encapsulated environment of the function definition.
|
||||
///
|
||||
/// Not available under `no_function` or `no_module`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get_encapsulated_environ(&self) -> Option<&EncapsulatedEnviron> {
|
||||
match self {
|
||||
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) | Self::Plugin(..) => None,
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Self::Script(.., environ) => environ.as_deref(),
|
||||
}
|
||||
}
|
||||
/// Get a reference to an iterator function.
|
||||
@@ -217,7 +253,7 @@ impl CallableFunction {
|
||||
impl From<crate::ast::ScriptFnDef> for CallableFunction {
|
||||
#[inline(always)]
|
||||
fn from(func: crate::ast::ScriptFnDef) -> Self {
|
||||
Self::Script(func.into())
|
||||
Self::Script(func.into(), None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +261,7 @@ impl From<crate::ast::ScriptFnDef> for CallableFunction {
|
||||
impl From<Shared<crate::ast::ScriptFnDef>> for CallableFunction {
|
||||
#[inline(always)]
|
||||
fn from(func: Shared<crate::ast::ScriptFnDef>) -> Self {
|
||||
Self::Script(func)
|
||||
Self::Script(func, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@ pub use call::ensure_no_data_race;
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub use call::is_anonymous_fn;
|
||||
pub use call::FnCallArgs;
|
||||
pub use callable_function::CallableFunction;
|
||||
pub use callable_function::{CallableFunction, EncapsulatedEnviron};
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub use func::Func;
|
||||
pub use hashing::{calc_fn_hash, calc_fn_hash_full, calc_var_hash, get_hasher, StraightHashMap};
|
||||
|
@@ -4,6 +4,7 @@
|
||||
use super::call::FnCallArgs;
|
||||
use crate::ast::ScriptFnDef;
|
||||
use crate::eval::{Caches, GlobalRuntimeState};
|
||||
use crate::func::EncapsulatedEnviron;
|
||||
use crate::{Dynamic, Engine, Position, RhaiResult, Scope, ERR};
|
||||
use std::mem;
|
||||
#[cfg(feature = "no_std")]
|
||||
@@ -28,6 +29,7 @@ impl Engine {
|
||||
caches: &mut Caches,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Dynamic,
|
||||
_environ: Option<&EncapsulatedEnviron>,
|
||||
fn_def: &ScriptFnDef,
|
||||
args: &mut FnCallArgs,
|
||||
rewind_scope: bool,
|
||||
@@ -84,12 +86,12 @@ impl Engine {
|
||||
let orig_fn_resolution_caches_len = caches.fn_resolution_caches_len();
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
let orig_constants = if let Some(ref environ) = fn_def.environ {
|
||||
let crate::ast::EncapsulatedEnviron {
|
||||
ref lib,
|
||||
ref imports,
|
||||
ref constants,
|
||||
} = **environ;
|
||||
let orig_constants = if let Some(environ) = _environ {
|
||||
let EncapsulatedEnviron {
|
||||
lib,
|
||||
imports,
|
||||
constants,
|
||||
} = environ;
|
||||
|
||||
imports
|
||||
.iter()
|
||||
@@ -124,8 +126,7 @@ impl Engine {
|
||||
_ => Err(ERR::ErrorInFunctionCall(
|
||||
fn_def.name.to_string(),
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
fn_def
|
||||
.environ
|
||||
_environ
|
||||
.as_deref()
|
||||
.and_then(|environ| environ.lib.id())
|
||||
.unwrap_or_else(|| global.source().unwrap_or(""))
|
||||
|
Reference in New Issue
Block a user