Remove Option from source and use empty string as no source.
This commit is contained in:
parent
8329baea29
commit
135b1f54c2
@ -209,9 +209,8 @@ impl Engine {
|
|||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let mut state = EvalState::new();
|
let mut state = EvalState::new();
|
||||||
if ast.source_raw().is_some() {
|
global.source = ast.source_raw().clone();
|
||||||
global.source = ast.source_raw().cloned();
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
global.embedded_module_resolver = ast.resolver().cloned();
|
global.embedded_module_resolver = ast.resolver().cloned();
|
||||||
|
@ -46,9 +46,8 @@ impl Engine {
|
|||||||
pub fn run_ast_with_scope(&self, scope: &mut Scope, ast: &AST) -> RhaiResultOf<()> {
|
pub fn run_ast_with_scope(&self, scope: &mut Scope, ast: &AST) -> RhaiResultOf<()> {
|
||||||
let global = &mut GlobalRuntimeState::new();
|
let global = &mut GlobalRuntimeState::new();
|
||||||
let mut state = EvalState::new();
|
let mut state = EvalState::new();
|
||||||
if ast.source_raw().is_some() {
|
global.source = ast.source_raw().clone();
|
||||||
global.source = ast.source_raw().cloned();
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
global.embedded_module_resolver = ast.resolver().cloned();
|
global.embedded_module_resolver = ast.resolver().cloned();
|
||||||
|
@ -17,7 +17,8 @@ use std::{
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AST {
|
pub struct AST {
|
||||||
/// Source of the [`AST`].
|
/// Source of the [`AST`].
|
||||||
source: Option<Identifier>,
|
/// No source if string is empty.
|
||||||
|
source: Identifier,
|
||||||
/// Global statements.
|
/// Global statements.
|
||||||
body: StmtBlock,
|
body: StmtBlock,
|
||||||
/// Script-defined functions.
|
/// Script-defined functions.
|
||||||
@ -45,7 +46,7 @@ impl AST {
|
|||||||
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
body: StmtBlock::new(statements, Position::NONE),
|
body: StmtBlock::new(statements, Position::NONE),
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
functions: functions.into(),
|
functions: functions.into(),
|
||||||
@ -63,7 +64,7 @@ impl AST {
|
|||||||
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
body: StmtBlock::new(statements, Position::NONE),
|
body: StmtBlock::new(statements, Position::NONE),
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
functions: functions.into(),
|
functions: functions.into(),
|
||||||
@ -111,7 +112,7 @@ impl AST {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
body: StmtBlock::NONE,
|
body: StmtBlock::NONE,
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
functions: crate::Module::new().into(),
|
functions: crate::Module::new().into(),
|
||||||
@ -123,13 +124,17 @@ impl AST {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
self.source.as_ref().map(|s| s.as_str())
|
if self.source.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&self.source)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Get a reference to the source.
|
/// Get a reference to the source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn source_raw(&self) -> Option<&Identifier> {
|
pub(crate) fn source_raw(&self) -> &Identifier {
|
||||||
self.source.as_ref()
|
&self.source
|
||||||
}
|
}
|
||||||
/// Set the source.
|
/// Set the source.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -139,13 +144,13 @@ impl AST {
|
|||||||
crate::Shared::get_mut(&mut self.functions)
|
crate::Shared::get_mut(&mut self.functions)
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|m| m.set_id(source.clone()));
|
.map(|m| m.set_id(source.clone()));
|
||||||
self.source = Some(source);
|
self.source = source;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Clear the source.
|
/// Clear the source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_source(&mut self) -> &mut Self {
|
pub fn clear_source(&mut self) -> &mut Self {
|
||||||
self.source = None;
|
self.source.clear();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Get the statements.
|
/// Get the statements.
|
||||||
@ -467,8 +472,6 @@ impl AST {
|
|||||||
(true, true) => StmtBlock::NONE,
|
(true, true) => StmtBlock::NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = other.source.clone().or_else(|| self.source.clone());
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
let functions = {
|
let functions = {
|
||||||
let mut functions = self.functions.as_ref().clone();
|
let mut functions = self.functions.as_ref().clone();
|
||||||
@ -476,12 +479,12 @@ impl AST {
|
|||||||
functions
|
functions
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(source) = source {
|
if !other.source.is_empty() {
|
||||||
Self::new_with_source(
|
Self::new_with_source(
|
||||||
merged,
|
merged,
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
functions,
|
functions,
|
||||||
source,
|
other.source.clone(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Self::new(
|
Self::new(
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::api::custom_syntax::CustomSyntax;
|
use crate::api::custom_syntax::CustomSyntax;
|
||||||
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
||||||
|
use crate::func::call::FnResolutionCache;
|
||||||
use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback};
|
use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback};
|
||||||
use crate::func::{get_hasher, CallableFunction, IteratorFn};
|
use crate::func::{get_hasher, CallableFunction, IteratorFn};
|
||||||
use crate::module::Namespace;
|
use crate::module::Namespace;
|
||||||
@ -507,7 +508,8 @@ pub struct GlobalRuntimeState {
|
|||||||
/// Stack of imported [modules][Module].
|
/// Stack of imported [modules][Module].
|
||||||
modules: StaticVec<Shared<Module>>,
|
modules: StaticVec<Shared<Module>>,
|
||||||
/// Source of the current context.
|
/// Source of the current context.
|
||||||
pub source: Option<Identifier>,
|
/// No source if the string is empty.
|
||||||
|
pub source: Identifier,
|
||||||
/// Number of operations performed.
|
/// Number of operations performed.
|
||||||
pub num_operations: u64,
|
pub num_operations: u64,
|
||||||
/// Number of modules loaded.
|
/// Number of modules loaded.
|
||||||
@ -539,7 +541,7 @@ impl GlobalRuntimeState {
|
|||||||
Self {
|
Self {
|
||||||
keys: StaticVec::new_const(),
|
keys: StaticVec::new_const(),
|
||||||
modules: StaticVec::new_const(),
|
modules: StaticVec::new_const(),
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
num_operations: 0,
|
num_operations: 0,
|
||||||
num_modules_loaded: 0,
|
num_modules_loaded: 0,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -629,11 +631,11 @@ impl GlobalRuntimeState {
|
|||||||
/// Get the specified function via its hash key from the stack of globally-imported [modules][Module].
|
/// Get the specified function via its hash key from the stack of globally-imported [modules][Module].
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&Identifier>)> {
|
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&str>)> {
|
||||||
self.modules
|
self.modules
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id())))
|
||||||
}
|
}
|
||||||
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of
|
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of
|
||||||
/// globally-imported [modules][Module]?
|
/// globally-imported [modules][Module]?
|
||||||
@ -746,20 +748,6 @@ impl fmt::Debug for GlobalRuntimeState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _(internals)_ An entry in a function resolution cache.
|
|
||||||
/// Exported under the `internals` feature only.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct FnResolutionCacheEntry {
|
|
||||||
/// Function.
|
|
||||||
pub func: CallableFunction,
|
|
||||||
/// Optional source.
|
|
||||||
pub source: Option<Box<str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// _(internals)_ A function resolution cache.
|
|
||||||
/// Exported under the `internals` feature only.
|
|
||||||
pub type FnResolutionCache = BTreeMap<u64, Option<Box<FnResolutionCacheEntry>>>;
|
|
||||||
|
|
||||||
/// _(internals)_ A type that holds all the current states of the [`Engine`].
|
/// _(internals)_ A type that holds all the current states of the [`Engine`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -844,7 +832,11 @@ impl<'x, 'px, 'pt> EvalContext<'_, 'x, 'px, '_, '_, '_, '_, 'pt> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
self.global.source.as_ref().map(|s| s.as_str())
|
if self.global.source.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&self.global.source)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// The current [`Scope`].
|
/// The current [`Scope`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -3041,8 +3033,8 @@ impl Engine {
|
|||||||
|
|
||||||
err_map.insert("message".into(), err.to_string().into());
|
err_map.insert("message".into(), err.to_string().into());
|
||||||
|
|
||||||
if let Some(ref source) = global.source {
|
if !global.source.is_empty() {
|
||||||
err_map.insert("source".into(), source.as_str().into());
|
err_map.insert("source".into(), global.source.clone().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if err_pos.is_none() {
|
if err_pos.is_none() {
|
||||||
@ -3174,7 +3166,11 @@ impl Engine {
|
|||||||
{
|
{
|
||||||
use crate::ModuleResolver;
|
use crate::ModuleResolver;
|
||||||
|
|
||||||
let source = global.source.as_ref().map(|s| s.as_str());
|
let source = if global.source.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(global.source.as_str())
|
||||||
|
};
|
||||||
let path_pos = expr.position();
|
let path_pos = expr.position();
|
||||||
|
|
||||||
let module = global
|
let module = global
|
||||||
|
@ -6,9 +6,8 @@ use super::{get_builtin_binary_op_fn, get_builtin_op_assignment_fn};
|
|||||||
use crate::api::default_limits::MAX_DYNAMIC_PARAMETERS;
|
use crate::api::default_limits::MAX_DYNAMIC_PARAMETERS;
|
||||||
use crate::ast::{Expr, FnCallHashes, Stmt};
|
use crate::ast::{Expr, FnCallHashes, Stmt};
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
EvalState, FnResolutionCacheEntry, GlobalRuntimeState, KEYWORD_DEBUG, KEYWORD_EVAL,
|
EvalState, GlobalRuntimeState, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
|
||||||
KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT,
|
KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
KEYWORD_TYPE_OF,
|
|
||||||
};
|
};
|
||||||
use crate::module::Namespace;
|
use crate::module::Namespace;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
@ -20,6 +19,7 @@ use crate::{
|
|||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
|
collections::BTreeMap,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
mem,
|
mem,
|
||||||
};
|
};
|
||||||
@ -125,6 +125,24 @@ pub fn ensure_no_data_race(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// _(internals)_ An entry in a function resolution cache.
|
||||||
|
/// Exported under the `internals` feature only.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FnResolutionCacheEntry {
|
||||||
|
/// Function.
|
||||||
|
pub func: CallableFunction,
|
||||||
|
/// Optional source.
|
||||||
|
/// No source if the string is empty.
|
||||||
|
pub source: Identifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// _(internals)_ A function resolution cache.
|
||||||
|
/// Exported under the `internals` feature only.
|
||||||
|
///
|
||||||
|
/// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree
|
||||||
|
/// level as possible.
|
||||||
|
pub type FnResolutionCache = BTreeMap<u64, Option<Box<FnResolutionCacheEntry>>>;
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
/// Generate the signature for a function call.
|
/// Generate the signature for a function call.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -206,14 +224,14 @@ impl Engine {
|
|||||||
.find_map(|m| {
|
.find_map(|m| {
|
||||||
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
||||||
func,
|
func,
|
||||||
source: m.id_raw().map(|s| s.to_string().into_boxed_str()),
|
source: m.id_raw().clone(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.global_modules.iter().find_map(|m| {
|
self.global_modules.iter().find_map(|m| {
|
||||||
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
|
||||||
func,
|
func,
|
||||||
source: m.id_raw().map(|s| s.to_string().into_boxed_str()),
|
source: m.id_raw().clone(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -222,7 +240,8 @@ impl Engine {
|
|||||||
.get_fn(hash)
|
.get_fn(hash)
|
||||||
.map(|(func, source)| FnResolutionCacheEntry {
|
.map(|(func, source)| FnResolutionCacheEntry {
|
||||||
func: func.clone(),
|
func: func.clone(),
|
||||||
source: source.map(|s| s.to_string().into_boxed_str()),
|
source: source
|
||||||
|
.map_or_else(|| Identifier::new_const(), Into::into),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -230,7 +249,7 @@ impl Engine {
|
|||||||
m.get_qualified_fn(hash).cloned().map(|func| {
|
m.get_qualified_fn(hash).cloned().map(|func| {
|
||||||
FnResolutionCacheEntry {
|
FnResolutionCacheEntry {
|
||||||
func,
|
func,
|
||||||
source: m.id_raw().map(|s| s.to_string().into_boxed_str()),
|
source: m.id_raw().clone(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -253,7 +272,7 @@ impl Engine {
|
|||||||
func: CallableFunction::from_method(
|
func: CallableFunction::from_method(
|
||||||
Box::new(f) as Box<FnAny>
|
Box::new(f) as Box<FnAny>
|
||||||
),
|
),
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -265,7 +284,7 @@ impl Engine {
|
|||||||
func: CallableFunction::from_method(
|
func: CallableFunction::from_method(
|
||||||
Box::new(f) as Box<FnAny>
|
Box::new(f) as Box<FnAny>
|
||||||
),
|
),
|
||||||
source: None,
|
source: Identifier::new_const(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.map(Box::new)
|
.map(Box::new)
|
||||||
@ -353,10 +372,15 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
let source = source
|
let source = if source.is_empty() {
|
||||||
.as_ref()
|
if parent_source.is_empty() {
|
||||||
.map(|s| &**s)
|
None
|
||||||
.or_else(|| parent_source.as_ref().map(|s| s.as_str()));
|
} else {
|
||||||
|
Some(parent_source.as_str())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(source.as_str())
|
||||||
|
};
|
||||||
|
|
||||||
let context = (self, name, source, &*global, lib, pos).into();
|
let context = (self, name, source, &*global, lib, pos).into();
|
||||||
|
|
||||||
@ -400,7 +424,11 @@ impl Engine {
|
|||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let source = global.source.as_ref().map(|s| s.as_str());
|
let source = if global.source.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(global.source.as_str())
|
||||||
|
};
|
||||||
(debug(&text, source, pos).into(), false)
|
(debug(&text, source, pos).into(), false)
|
||||||
} else {
|
} else {
|
||||||
(Dynamic::UNIT, false)
|
(Dynamic::UNIT, false)
|
||||||
@ -572,7 +600,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Script-defined function call?
|
// Script-defined function call?
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
if let Some(FnResolutionCacheEntry { func, source }) = self
|
if let Some(FnResolutionCacheEntry { func, mut source }) = self
|
||||||
.resolve_fn(
|
.resolve_fn(
|
||||||
global,
|
global,
|
||||||
state,
|
state,
|
||||||
@ -603,13 +631,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mem::swap(&mut global.source, &mut source);
|
||||||
|
|
||||||
let result = if _is_method_call {
|
let result = if _is_method_call {
|
||||||
// Method call of script function - map first argument to `this`
|
// Method call of script function - map first argument to `this`
|
||||||
let (first_arg, rest_args) = args.split_first_mut().expect("not empty");
|
let (first_arg, rest_args) = args.split_first_mut().expect("not empty");
|
||||||
|
|
||||||
let orig_source = global.source.take();
|
|
||||||
global.source = source.map(Into::into);
|
|
||||||
|
|
||||||
let level = _level + 1;
|
let level = _level + 1;
|
||||||
|
|
||||||
let result = self.call_script_fn(
|
let result = self.call_script_fn(
|
||||||
@ -625,9 +652,6 @@ impl Engine {
|
|||||||
level,
|
level,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore the original source
|
|
||||||
global.source = orig_source;
|
|
||||||
|
|
||||||
result?
|
result?
|
||||||
} else {
|
} else {
|
||||||
// Normal call of script function
|
// Normal call of script function
|
||||||
@ -641,18 +665,12 @@ impl Engine {
|
|||||||
.change_first_arg_to_copy(args);
|
.change_first_arg_to_copy(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
let orig_source = global.source.take();
|
|
||||||
global.source = source.map(Into::into);
|
|
||||||
|
|
||||||
let level = _level + 1;
|
let level = _level + 1;
|
||||||
|
|
||||||
let result = self.call_script_fn(
|
let result = self.call_script_fn(
|
||||||
scope, global, state, lib, &mut None, func, args, pos, true, level,
|
scope, global, state, lib, &mut None, func, args, pos, true, level,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore the original source
|
|
||||||
global.source = orig_source;
|
|
||||||
|
|
||||||
// Restore the original reference
|
// Restore the original reference
|
||||||
if let Some(bk) = backup {
|
if let Some(bk) = backup {
|
||||||
bk.restore_first_arg(args)
|
bk.restore_first_arg(args)
|
||||||
@ -661,6 +679,9 @@ impl Engine {
|
|||||||
result?
|
result?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Restore the original source
|
||||||
|
mem::swap(&mut global.source, &mut source);
|
||||||
|
|
||||||
return Ok((result, false));
|
return Ok((result, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1058,11 +1079,7 @@ impl Engine {
|
|||||||
return result.map_err(|err| {
|
return result.map_err(|err| {
|
||||||
ERR::ErrorInFunctionCall(
|
ERR::ErrorInFunctionCall(
|
||||||
KEYWORD_EVAL.to_string(),
|
KEYWORD_EVAL.to_string(),
|
||||||
global
|
global.source.to_string(),
|
||||||
.source
|
|
||||||
.as_ref()
|
|
||||||
.map(Identifier::to_string)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
err,
|
err,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
@ -1265,7 +1282,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
let new_scope = &mut Scope::new();
|
let new_scope = &mut Scope::new();
|
||||||
|
|
||||||
let mut source = module.id_raw().cloned();
|
let mut source = module.id_raw().clone();
|
||||||
mem::swap(&mut global.source, &mut source);
|
mem::swap(&mut global.source, &mut source);
|
||||||
|
|
||||||
let level = level + 1;
|
let level = level + 1;
|
||||||
|
@ -90,7 +90,7 @@ impl<'a, M: AsRef<[&'a Module]> + ?Sized, S: AsRef<str> + 'a + ?Sized>
|
|||||||
Self {
|
Self {
|
||||||
engine: value.0,
|
engine: value.0,
|
||||||
fn_name: value.1.as_ref(),
|
fn_name: value.1.as_ref(),
|
||||||
source: value.2.map(|v| v.as_ref()),
|
source: value.2.map(S::as_ref),
|
||||||
global: Some(value.3),
|
global: Some(value.3),
|
||||||
lib: value.4.as_ref(),
|
lib: value.4.as_ref(),
|
||||||
pos: value.5,
|
pos: value.5,
|
||||||
@ -156,7 +156,7 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
Self {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
fn_name: fn_name.as_ref(),
|
fn_name: fn_name.as_ref(),
|
||||||
source: source.map(|v| v.as_ref()),
|
source: source.map(S::as_ref),
|
||||||
global: Some(global),
|
global: Some(global),
|
||||||
lib,
|
lib,
|
||||||
pos,
|
pos,
|
||||||
|
@ -47,9 +47,8 @@ impl Engine {
|
|||||||
fn_def
|
fn_def
|
||||||
.lib
|
.lib
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|m| m.id().map(|id| id.to_string()))
|
.and_then(|m| m.id().map(str::to_string))
|
||||||
.or_else(|| global.source.as_ref().map(|s| s.to_string()))
|
.unwrap_or_else(|| global.source.to_string()),
|
||||||
.unwrap_or_default(),
|
|
||||||
err,
|
err,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
|
@ -247,7 +247,10 @@ pub use ast::{
|
|||||||
pub use ast::FloatWrapper;
|
pub use ast::FloatWrapper;
|
||||||
|
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
pub use engine::{EvalState, FnResolutionCache, FnResolutionCacheEntry, GlobalRuntimeState};
|
pub use engine::{EvalState, GlobalRuntimeState};
|
||||||
|
|
||||||
|
#[cfg(feature = "internals")]
|
||||||
|
pub use func::call::{FnResolutionCache, FnResolutionCacheEntry};
|
||||||
|
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
pub use module::Namespace;
|
pub use module::Namespace;
|
||||||
|
@ -131,7 +131,8 @@ pub fn calc_native_fn_hash(
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
id: Option<Identifier>,
|
/// No ID if string is empty.
|
||||||
|
id: Identifier,
|
||||||
/// Is this module internal?
|
/// Is this module internal?
|
||||||
pub(crate) internal: bool,
|
pub(crate) internal: bool,
|
||||||
/// Is this module part of a standard library?
|
/// Is this module part of a standard library?
|
||||||
@ -170,8 +171,9 @@ impl fmt::Debug for Module {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut d = f.debug_struct("Module");
|
let mut d = f.debug_struct("Module");
|
||||||
|
|
||||||
self.id.as_ref().map(|id| d.field("id", id));
|
if !self.id.is_empty() {
|
||||||
|
d.field("id", &self.id);
|
||||||
|
}
|
||||||
if !self.modules.is_empty() {
|
if !self.modules.is_empty() {
|
||||||
d.field(
|
d.field(
|
||||||
"modules",
|
"modules",
|
||||||
@ -241,7 +243,7 @@ impl Module {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: None,
|
id: Identifier::new_const(),
|
||||||
internal: false,
|
internal: false,
|
||||||
standard: false,
|
standard: false,
|
||||||
modules: BTreeMap::new(),
|
modules: BTreeMap::new(),
|
||||||
@ -270,18 +272,24 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn id(&self) -> Option<&str> {
|
pub fn id(&self) -> Option<&str> {
|
||||||
self.id_raw().map(|s| s.as_str())
|
if self.id_raw().is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.id_raw())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ID of the [`Module`] as an [`Identifier`], if any.
|
/// Get the ID of the [`Module`] as an [`Identifier`], if any.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) const fn id_raw(&self) -> Option<&Identifier> {
|
pub(crate) const fn id_raw(&self) -> &Identifier {
|
||||||
self.id.as_ref()
|
&self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the ID of the [`Module`].
|
/// Set the ID of the [`Module`].
|
||||||
///
|
///
|
||||||
|
/// If the string is empty, it is equivalent to clearing the ID.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -292,7 +300,7 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_id(&mut self, id: impl Into<Identifier>) -> &mut Self {
|
pub fn set_id(&mut self, id: impl Into<Identifier>) -> &mut Self {
|
||||||
self.id = Some(id.into());
|
self.id = id.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Clear the ID of the [`Module`].
|
/// Clear the ID of the [`Module`].
|
||||||
@ -309,7 +317,7 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_id(&mut self) -> &mut Self {
|
pub fn clear_id(&mut self) -> &mut Self {
|
||||||
self.id = None;
|
self.id.clear();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,11 +1624,7 @@ impl Module {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = ast.source_raw() {
|
module.set_id(ast.source_raw().clone());
|
||||||
module.set_id(s.clone());
|
|
||||||
} else {
|
|
||||||
module.clear_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.build_index();
|
module.build_index();
|
||||||
|
|
||||||
|
@ -80,21 +80,21 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", ast),
|
format!("{:?}", ast),
|
||||||
"AST { source: None, body: Block[Expr(123 @ 1:53)], functions: Module, resolver: None }"
|
"AST { source: \"\", body: Block[Expr(123 @ 1:53)], functions: Module, resolver: None }"
|
||||||
);
|
);
|
||||||
|
|
||||||
let ast = engine.compile("const DECISION = false; if DECISION { 42 } else { 123 }")?;
|
let ast = engine.compile("const DECISION = false; if DECISION { 42 } else { 123 }")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", ast),
|
format!("{:?}", ast),
|
||||||
r#"AST { source: None, body: Block[Var(false @ 1:18, "DECISION" @ 1:7, (Constant), 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"#
|
r#"AST { source: "", body: Block[Var(false @ 1:18, "DECISION" @ 1:7, (Constant), 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", ast),
|
format!("{:?}", ast),
|
||||||
"AST { source: None, body: Block[], functions: Module, resolver: None }"
|
"AST { source: \"\", body: Block[], functions: Module, resolver: None }"
|
||||||
);
|
);
|
||||||
|
|
||||||
engine.set_optimization_level(OptimizationLevel::Full);
|
engine.set_optimization_level(OptimizationLevel::Full);
|
||||||
@ -103,7 +103,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", ast),
|
format!("{:?}", ast),
|
||||||
"AST { source: None, body: Block[Expr(42 @ 1:1)], functions: Module, resolver: None }"
|
"AST { source: \"\", body: Block[Expr(42 @ 1:1)], functions: Module, resolver: None }"
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user