Use ImmutableString for source.
This commit is contained in:
parent
d0998a44b9
commit
4100e6da64
@ -217,7 +217,7 @@ impl Engine {
|
|||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let mut caches = Caches::new();
|
let mut caches = Caches::new();
|
||||||
global.source = ast.source_raw().clone();
|
global.source = ast.source_raw().cloned();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
let orig_embedded_module_resolver = std::mem::replace(
|
let orig_embedded_module_resolver = std::mem::replace(
|
||||||
|
@ -113,7 +113,7 @@ 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 caches = &mut Caches::new();
|
let caches = &mut Caches::new();
|
||||||
let global = &mut GlobalRuntimeState::new(self);
|
let global = &mut GlobalRuntimeState::new(self);
|
||||||
global.source = ast.source_raw().clone();
|
global.source = ast.source_raw().cloned();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module defining the AST (abstract syntax tree).
|
//! Module defining the AST (abstract syntax tree).
|
||||||
|
|
||||||
use super::{ASTFlags, Expr, FnAccess, Stmt, StmtBlock, StmtBlockContainer};
|
use super::{ASTFlags, Expr, FnAccess, Stmt, StmtBlock, StmtBlockContainer};
|
||||||
use crate::{Dynamic, FnNamespace, Identifier, Position};
|
use crate::{Dynamic, FnNamespace, ImmutableString, Position};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -20,8 +20,7 @@ use std::{
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AST {
|
pub struct AST {
|
||||||
/// Source of the [`AST`].
|
/// Source of the [`AST`].
|
||||||
/// No source if string is empty.
|
source: Option<ImmutableString>,
|
||||||
source: Identifier,
|
|
||||||
/// [`AST`] documentation.
|
/// [`AST`] documentation.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString,
|
doc: crate::SmartString,
|
||||||
@ -98,7 +97,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: Identifier::new_const(),
|
source: None,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString::new_const(),
|
doc: crate::SmartString::new_const(),
|
||||||
body: StmtBlock::new(statements, Position::NONE, Position::NONE),
|
body: StmtBlock::new(statements, Position::NONE, Position::NONE),
|
||||||
@ -133,7 +132,7 @@ impl AST {
|
|||||||
pub fn new_with_source(
|
pub fn new_with_source(
|
||||||
statements: impl IntoIterator<Item = Stmt>,
|
statements: impl IntoIterator<Item = Stmt>,
|
||||||
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
|
||||||
source: impl Into<Identifier>,
|
source: impl Into<ImmutableString>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut ast = Self::new(
|
let mut ast = Self::new(
|
||||||
statements,
|
statements,
|
||||||
@ -148,7 +147,7 @@ impl AST {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: Identifier::new_const(),
|
source: None,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString::new_const(),
|
doc: crate::SmartString::new_const(),
|
||||||
body: StmtBlock::NONE,
|
body: StmtBlock::NONE,
|
||||||
@ -159,36 +158,39 @@ impl AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the source, if any.
|
/// Get the source, if any.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
if self.source.is_empty() {
|
self.source.as_ref().map(|s| s.as_str())
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.source.as_str())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// Get a reference to the source.
|
/// Get a reference to the source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) const fn source_raw(&self) -> &Identifier {
|
pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
|
||||||
&self.source
|
self.source.as_ref()
|
||||||
}
|
}
|
||||||
/// Set the source.
|
/// Set the source.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_source(&mut self, source: impl Into<Identifier>) -> &mut Self {
|
pub fn set_source(&mut self, source: impl Into<ImmutableString>) -> &mut Self {
|
||||||
let source = source.into();
|
let source = source.into();
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
crate::Shared::get_mut(&mut self.lib)
|
crate::Shared::get_mut(&mut self.lib)
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|m| m.set_id(source.clone()));
|
.map(|m| m.set_id(source.clone()));
|
||||||
self.source = source;
|
|
||||||
|
if source.is_empty() {
|
||||||
|
self.source = None;
|
||||||
|
} else {
|
||||||
|
self.source = Some(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.clear();
|
self.source = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Get the documentation (if any).
|
/// Get the documentation (if any).
|
||||||
@ -559,18 +561,18 @@ impl AST {
|
|||||||
lib
|
lib
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut _ast = if other.source.is_empty() {
|
let mut _ast = if let Some(ref source) = other.source {
|
||||||
Self::new(
|
|
||||||
merged,
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
lib,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Self::new_with_source(
|
Self::new_with_source(
|
||||||
merged,
|
merged,
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
lib,
|
lib,
|
||||||
other.source.clone(),
|
source.clone(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Self::new(
|
||||||
|
merged,
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
lib,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::func::{CallableFunction, StraightHashMap};
|
use crate::func::{CallableFunction, StraightHashMap};
|
||||||
use crate::types::BloomFilterU64;
|
use crate::types::BloomFilterU64;
|
||||||
use crate::{Identifier, StaticVec};
|
use crate::{ImmutableString, StaticVec};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -14,7 +14,7 @@ pub struct FnResolutionCacheEntry {
|
|||||||
/// Function.
|
/// Function.
|
||||||
pub func: CallableFunction,
|
pub func: CallableFunction,
|
||||||
/// Optional source.
|
/// Optional source.
|
||||||
pub source: Option<Box<Identifier>>,
|
pub source: Option<ImmutableString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _(internals)_ A function resolution cache with a bloom filter.
|
/// _(internals)_ A function resolution cache with a bloom filter.
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
use super::{EvalContext, GlobalRuntimeState};
|
use super::{EvalContext, GlobalRuntimeState};
|
||||||
use crate::ast::{ASTNode, Expr, Stmt};
|
use crate::ast::{ASTNode, Expr, Stmt};
|
||||||
use crate::{Dynamic, Engine, EvalAltResult, Identifier, Module, Position, RhaiResultOf, Scope};
|
use crate::{
|
||||||
|
Dynamic, Engine, EvalAltResult, Identifier, ImmutableString, Module, Position, RhaiResultOf,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{fmt, iter::repeat, mem};
|
use std::{fmt, iter::repeat, mem};
|
||||||
@ -226,8 +229,8 @@ pub struct CallStackFrame {
|
|||||||
pub fn_name: Identifier,
|
pub fn_name: Identifier,
|
||||||
/// Copies of function call arguments, if any.
|
/// Copies of function call arguments, if any.
|
||||||
pub args: crate::StaticVec<Dynamic>,
|
pub args: crate::StaticVec<Dynamic>,
|
||||||
/// Source of the function, empty if none.
|
/// Source of the function.
|
||||||
pub source: Identifier,
|
pub source: Option<ImmutableString>,
|
||||||
/// [Position][`Position`] of the function call.
|
/// [Position][`Position`] of the function call.
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
@ -243,8 +246,8 @@ impl fmt::Display for CallStackFrame {
|
|||||||
fp.finish()?;
|
fp.finish()?;
|
||||||
|
|
||||||
if !self.pos.is_none() {
|
if !self.pos.is_none() {
|
||||||
if !self.source.is_empty() {
|
if let Some(ref source) = self.source {
|
||||||
write!(f, ": {}", self.source)?;
|
write!(f, ": {source}")?;
|
||||||
}
|
}
|
||||||
write!(f, " @ {:?}", self.pos)?;
|
write!(f, " @ {:?}", self.pos)?;
|
||||||
}
|
}
|
||||||
@ -295,13 +298,13 @@ impl Debugger {
|
|||||||
&mut self,
|
&mut self,
|
||||||
fn_name: impl Into<Identifier>,
|
fn_name: impl Into<Identifier>,
|
||||||
args: crate::StaticVec<Dynamic>,
|
args: crate::StaticVec<Dynamic>,
|
||||||
source: impl Into<Identifier>,
|
source: Option<ImmutableString>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) {
|
) {
|
||||||
self.call_stack.push(CallStackFrame {
|
self.call_stack.push(CallStackFrame {
|
||||||
fn_name: fn_name.into(),
|
fn_name: fn_name.into(),
|
||||||
args,
|
args,
|
||||||
source: source.into(),
|
source,
|
||||||
pos,
|
pos,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -487,7 +490,10 @@ impl Engine {
|
|||||||
|
|
||||||
let event = match event {
|
let event = match event {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => match global.debugger.is_break_point(&global.source, node) {
|
None => match global
|
||||||
|
.debugger
|
||||||
|
.is_break_point(global.source().unwrap_or(""), node)
|
||||||
|
{
|
||||||
Some(bp) => DebuggerEvent::BreakPoint(bp),
|
Some(bp) => DebuggerEvent::BreakPoint(bp),
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
},
|
},
|
||||||
@ -512,17 +518,12 @@ impl Engine {
|
|||||||
event: DebuggerEvent,
|
event: DebuggerEvent,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
|
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
|
||||||
let source = global.source.clone();
|
let src = global.source_raw().cloned();
|
||||||
let source = if source.is_empty() {
|
let src = src.as_ref().map(|s| s.as_str());
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(source.as_str())
|
|
||||||
};
|
|
||||||
|
|
||||||
let context = crate::EvalContext::new(self, scope, global, None, lib, this_ptr, level);
|
let context = crate::EvalContext::new(self, scope, global, None, lib, this_ptr, level);
|
||||||
|
|
||||||
if let Some((.., ref on_debugger)) = self.debugger {
|
if let Some((.., ref on_debugger)) = self.debugger {
|
||||||
let command = on_debugger(context, event, node, source, node.position())?;
|
let command = on_debugger(context, event, node, src, node.position())?;
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
DebuggerCommand::Continue => {
|
DebuggerCommand::Continue => {
|
||||||
|
@ -58,11 +58,7 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, '
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
if self.global.source.is_empty() {
|
self.global.source()
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.global.source.as_str())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// The current [`Scope`].
|
/// The current [`Scope`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Global runtime state.
|
//! Global runtime state.
|
||||||
|
|
||||||
use crate::{Dynamic, Engine, Identifier};
|
use crate::{Dynamic, Engine, ImmutableString};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{fmt, marker::PhantomData};
|
use std::{fmt, marker::PhantomData};
|
||||||
@ -9,7 +9,7 @@ use std::{fmt, marker::PhantomData};
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub type GlobalConstants =
|
pub type GlobalConstants =
|
||||||
crate::Shared<crate::Locked<std::collections::BTreeMap<crate::ImmutableString, Dynamic>>>;
|
crate::Shared<crate::Locked<std::collections::BTreeMap<ImmutableString, Dynamic>>>;
|
||||||
|
|
||||||
/// _(internals)_ Global runtime states.
|
/// _(internals)_ Global runtime states.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
@ -25,14 +25,14 @@ pub type GlobalConstants =
|
|||||||
pub struct GlobalRuntimeState<'a> {
|
pub struct GlobalRuntimeState<'a> {
|
||||||
/// Names of imported [modules][crate::Module].
|
/// Names of imported [modules][crate::Module].
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
imports: crate::StaticVec<crate::ImmutableString>,
|
imports: crate::StaticVec<ImmutableString>,
|
||||||
/// Stack of imported [modules][crate::Module].
|
/// Stack of imported [modules][crate::Module].
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
modules: crate::StaticVec<crate::Shared<crate::Module>>,
|
modules: crate::StaticVec<crate::Shared<crate::Module>>,
|
||||||
/// Source of the current context.
|
/// Source of the current context.
|
||||||
///
|
///
|
||||||
/// No source if the string is empty.
|
/// No source if the string is empty.
|
||||||
pub source: Identifier,
|
pub source: Option<ImmutableString>,
|
||||||
/// Number of operations performed.
|
/// Number of operations performed.
|
||||||
pub num_operations: u64,
|
pub num_operations: u64,
|
||||||
/// Number of modules loaded.
|
/// Number of modules loaded.
|
||||||
@ -84,7 +84,7 @@ impl GlobalRuntimeState<'_> {
|
|||||||
imports: crate::StaticVec::new_const(),
|
imports: crate::StaticVec::new_const(),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
modules: crate::StaticVec::new_const(),
|
modules: crate::StaticVec::new_const(),
|
||||||
source: Identifier::new_const(),
|
source: None,
|
||||||
num_operations: 0,
|
num_operations: 0,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
num_modules_loaded: 0,
|
num_modules_loaded: 0,
|
||||||
@ -168,7 +168,7 @@ impl GlobalRuntimeState<'_> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_import(
|
pub fn push_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<crate::ImmutableString>,
|
name: impl Into<ImmutableString>,
|
||||||
module: impl Into<crate::Shared<crate::Module>>,
|
module: impl Into<crate::Shared<crate::Module>>,
|
||||||
) {
|
) {
|
||||||
self.imports.push(name.into());
|
self.imports.push(name.into());
|
||||||
@ -202,7 +202,7 @@ impl GlobalRuntimeState<'_> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn iter_imports_raw(
|
pub(crate) fn iter_imports_raw(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (&crate::ImmutableString, &crate::Shared<crate::Module>)> {
|
) -> impl Iterator<Item = (&ImmutableString, &crate::Shared<crate::Module>)> {
|
||||||
self.imports.iter().zip(self.modules.iter()).rev()
|
self.imports.iter().zip(self.modules.iter()).rev()
|
||||||
}
|
}
|
||||||
/// Get an iterator to the stack of globally-imported [modules][crate::Module] in forward order.
|
/// Get an iterator to the stack of globally-imported [modules][crate::Module] in forward order.
|
||||||
@ -212,7 +212,7 @@ impl GlobalRuntimeState<'_> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn scan_imports_raw(
|
pub fn scan_imports_raw(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = (&crate::ImmutableString, &crate::Shared<crate::Module>)> {
|
) -> impl Iterator<Item = (&ImmutableString, &crate::Shared<crate::Module>)> {
|
||||||
self.imports.iter().zip(self.modules.iter())
|
self.imports.iter().zip(self.modules.iter())
|
||||||
}
|
}
|
||||||
/// Can the particular function with [`Dynamic`] parameter(s) exist in the stack of
|
/// Can the particular function with [`Dynamic`] parameter(s) exist in the stack of
|
||||||
@ -247,11 +247,11 @@ impl GlobalRuntimeState<'_> {
|
|||||||
pub fn get_qualified_fn(
|
pub fn get_qualified_fn(
|
||||||
&self,
|
&self,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
) -> Option<(&crate::func::CallableFunction, Option<&str>)> {
|
) -> Option<(&crate::func::CallableFunction, Option<&ImmutableString>)> {
|
||||||
self.modules
|
self.modules
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id())))
|
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||||
}
|
}
|
||||||
/// 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][crate::Module]?
|
/// globally-imported [modules][crate::Module]?
|
||||||
@ -278,14 +278,16 @@ impl GlobalRuntimeState<'_> {
|
|||||||
.find_map(|m| m.get_qualified_iter(id))
|
.find_map(|m| m.get_qualified_iter(id))
|
||||||
}
|
}
|
||||||
/// Get the current source.
|
/// Get the current source.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
if self.source.is_empty() {
|
self.source.as_ref().map(|s| s.as_str())
|
||||||
None
|
}
|
||||||
} else {
|
/// Get the current source.
|
||||||
Some(self.source.as_str())
|
#[inline(always)]
|
||||||
}
|
#[must_use]
|
||||||
|
pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
|
||||||
|
self.source.as_ref()
|
||||||
}
|
}
|
||||||
/// Get the pre-calculated index getter hash.
|
/// Get the pre-calculated index getter hash.
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
@ -317,10 +319,10 @@ impl GlobalRuntimeState<'_> {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
impl IntoIterator for GlobalRuntimeState<'_> {
|
impl IntoIterator for GlobalRuntimeState<'_> {
|
||||||
type Item = (crate::ImmutableString, crate::Shared<crate::Module>);
|
type Item = (ImmutableString, crate::Shared<crate::Module>);
|
||||||
type IntoIter = std::iter::Rev<
|
type IntoIter = std::iter::Rev<
|
||||||
std::iter::Zip<
|
std::iter::Zip<
|
||||||
smallvec::IntoIter<[crate::ImmutableString; crate::STATIC_VEC_INLINE_SIZE]>,
|
smallvec::IntoIter<[ImmutableString; crate::STATIC_VEC_INLINE_SIZE]>,
|
||||||
smallvec::IntoIter<[crate::Shared<crate::Module>; crate::STATIC_VEC_INLINE_SIZE]>,
|
smallvec::IntoIter<[crate::Shared<crate::Module>; crate::STATIC_VEC_INLINE_SIZE]>,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
@ -332,10 +334,10 @@ impl IntoIterator for GlobalRuntimeState<'_> {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
impl<'a> IntoIterator for &'a GlobalRuntimeState<'_> {
|
impl<'a> IntoIterator for &'a GlobalRuntimeState<'_> {
|
||||||
type Item = (&'a crate::ImmutableString, &'a crate::Shared<crate::Module>);
|
type Item = (&'a ImmutableString, &'a crate::Shared<crate::Module>);
|
||||||
type IntoIter = std::iter::Rev<
|
type IntoIter = std::iter::Rev<
|
||||||
std::iter::Zip<
|
std::iter::Zip<
|
||||||
std::slice::Iter<'a, crate::ImmutableString>,
|
std::slice::Iter<'a, ImmutableString>,
|
||||||
std::slice::Iter<'a, crate::Shared<crate::Module>>,
|
std::slice::Iter<'a, crate::Shared<crate::Module>>,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
@ -346,7 +348,7 @@ impl<'a> IntoIterator for &'a GlobalRuntimeState<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
impl<K: Into<crate::ImmutableString>, M: Into<crate::Shared<crate::Module>>> Extend<(K, M)>
|
impl<K: Into<ImmutableString>, M: Into<crate::Shared<crate::Module>>> Extend<(K, M)>
|
||||||
for GlobalRuntimeState<'_>
|
for GlobalRuntimeState<'_>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -719,8 +719,8 @@ impl Engine {
|
|||||||
|
|
||||||
err_map.insert("message".into(), err.to_string().into());
|
err_map.insert("message".into(), err.to_string().into());
|
||||||
|
|
||||||
if !global.source.is_empty() {
|
if let Some(ref source) = global.source {
|
||||||
err_map.insert("source".into(), global.source.clone().into());
|
err_map.insert("source".into(), source.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !err_pos.is_none() {
|
if !err_pos.is_none() {
|
||||||
|
@ -218,7 +218,7 @@ impl Engine {
|
|||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.chain(self.global_modules.iter().map(|m| m.as_ref()))
|
.chain(self.global_modules.iter().map(|m| m.as_ref()))
|
||||||
.find_map(|m| m.get_fn(hash).map(|f| (f, m.id())));
|
.find_map(|m| m.get_fn(hash).map(|f| (f, m.id_raw())));
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
let func = if args.is_none() {
|
let func = if args.is_none() {
|
||||||
@ -228,7 +228,7 @@ impl Engine {
|
|||||||
func.or_else(|| _global.get_qualified_fn(hash)).or_else(|| {
|
func.or_else(|| _global.get_qualified_fn(hash)).or_else(|| {
|
||||||
self.global_sub_modules
|
self.global_sub_modules
|
||||||
.values()
|
.values()
|
||||||
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id())))
|
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ impl Engine {
|
|||||||
// Specific version found
|
// Specific version found
|
||||||
let new_entry = Some(FnResolutionCacheEntry {
|
let new_entry = Some(FnResolutionCacheEntry {
|
||||||
func: f.clone(),
|
func: f.clone(),
|
||||||
source: s.map(|s| Box::new(s.into())),
|
source: s.cloned(),
|
||||||
});
|
});
|
||||||
return if cache.filter.is_absent_and_set(hash) {
|
return if cache.filter.is_absent_and_set(hash) {
|
||||||
// Do not cache "one-hit wonders"
|
// Do not cache "one-hit wonders"
|
||||||
@ -358,7 +358,6 @@ impl Engine {
|
|||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
self.track_operation(global, pos)?;
|
self.track_operation(global, pos)?;
|
||||||
|
|
||||||
let parent_source = global.source.clone();
|
|
||||||
let op_assign = if is_op_assign {
|
let op_assign = if is_op_assign {
|
||||||
Token::lookup_from_syntax(name)
|
Token::lookup_from_syntax(name)
|
||||||
} else {
|
} else {
|
||||||
@ -398,24 +397,19 @@ impl Engine {
|
|||||||
backup.change_first_arg_to_copy(args);
|
backup.change_first_arg_to_copy(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
let source = match (source, parent_source.as_str()) {
|
|
||||||
(None, "") => None,
|
|
||||||
(None, s) => Some(s),
|
|
||||||
(Some(s), ..) => Some(s.as_str()),
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
if self.debugger.is_some() {
|
if self.debugger.is_some() {
|
||||||
global.debugger.push_call_stack_frame(
|
global.debugger.push_call_stack_frame(
|
||||||
name,
|
name,
|
||||||
args.iter().map(|v| (*v).clone()).collect(),
|
args.iter().map(|v| (*v).clone()).collect(),
|
||||||
source.unwrap_or(""),
|
source.clone().or_else(|| global.source.clone()),
|
||||||
pos,
|
pos,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
let context = (self, name, source, &*global, lib, pos, level).into();
|
let src = source.as_ref().map(|s| s.as_str());
|
||||||
|
let context = (self, name, src, &*global, lib, pos, level).into();
|
||||||
|
|
||||||
let result = if func.is_plugin_fn() {
|
let result = if func.is_plugin_fn() {
|
||||||
let f = func.get_plugin_fn().unwrap();
|
let f = func.get_plugin_fn().unwrap();
|
||||||
@ -484,12 +478,7 @@ impl Engine {
|
|||||||
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
||||||
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
||||||
})?;
|
})?;
|
||||||
let source = if global.source.is_empty() {
|
((*self.debug)(&text, global.source(), pos).into(), false)
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(global.source.as_str())
|
|
||||||
};
|
|
||||||
((*self.debug)(&text, source, pos).into(), false)
|
|
||||||
}
|
}
|
||||||
_ => (result, is_method),
|
_ => (result, is_method),
|
||||||
});
|
});
|
||||||
@ -685,12 +674,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let orig_source = mem::replace(
|
let orig_source = mem::replace(&mut global.source, source.clone());
|
||||||
&mut global.source,
|
|
||||||
source
|
|
||||||
.as_ref()
|
|
||||||
.map_or(crate::Identifier::new_const(), |s| (**s).clone()),
|
|
||||||
);
|
|
||||||
|
|
||||||
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`
|
||||||
@ -1172,7 +1156,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.source.to_string(),
|
global.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
@ -1416,14 +1400,13 @@ impl Engine {
|
|||||||
Some(f) if f.is_script() => {
|
Some(f) if f.is_script() => {
|
||||||
let fn_def = f.get_script_fn_def().expect("script-defined function");
|
let fn_def = f.get_script_fn_def().expect("script-defined function");
|
||||||
let new_scope = &mut Scope::new();
|
let new_scope = &mut Scope::new();
|
||||||
let mut source = module.id_raw().clone();
|
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
||||||
mem::swap(&mut global.source, &mut source);
|
|
||||||
|
|
||||||
let result = self.call_script_fn(
|
let result = self.call_script_fn(
|
||||||
new_scope, global, caches, lib, &mut None, fn_def, &mut args, true, pos, level,
|
new_scope, global, caches, lib, &mut None, fn_def, &mut args, true, pos, level,
|
||||||
);
|
);
|
||||||
|
|
||||||
global.source = source;
|
global.source = orig_source;
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ impl Engine {
|
|||||||
|
|
||||||
Err(ERR::ErrorInFunctionCall(
|
Err(ERR::ErrorInFunctionCall(
|
||||||
name,
|
name,
|
||||||
source.unwrap_or_else(|| global.source.to_string()),
|
source.unwrap_or_else(|| global.source().unwrap_or("").to_string()),
|
||||||
err,
|
err,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
|
@ -160,8 +160,7 @@ pub fn calc_native_fn_hash<'a>(
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
/// No ID if string is empty.
|
id: Option<ImmutableString>,
|
||||||
id: Identifier,
|
|
||||||
/// Module documentation.
|
/// Module documentation.
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString,
|
doc: crate::SmartString,
|
||||||
@ -292,7 +291,7 @@ impl Module {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: Identifier::new_const(),
|
id: None,
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
doc: crate::SmartString::new_const(),
|
doc: crate::SmartString::new_const(),
|
||||||
internal: false,
|
internal: false,
|
||||||
@ -324,18 +323,14 @@ impl Module {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn id(&self) -> Option<&str> {
|
pub fn id(&self) -> Option<&str> {
|
||||||
if self.id_raw().is_empty() {
|
self.id.as_ref().map(|s| s.as_str())
|
||||||
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) -> &Identifier {
|
pub(crate) const fn id_raw(&self) -> Option<&ImmutableString> {
|
||||||
&self.id
|
self.id.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the ID of the [`Module`].
|
/// Set the ID of the [`Module`].
|
||||||
@ -351,8 +346,15 @@ impl Module {
|
|||||||
/// assert_eq!(module.id(), Some("hello"));
|
/// assert_eq!(module.id(), Some("hello"));
|
||||||
/// ```
|
/// ```
|
||||||
#[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<ImmutableString>) -> &mut Self {
|
||||||
self.id = id.into();
|
let id = id.into();
|
||||||
|
|
||||||
|
if id.is_empty() {
|
||||||
|
self.id = None;
|
||||||
|
} else {
|
||||||
|
self.id = Some(id);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +372,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.clear();
|
self.id = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +436,7 @@ impl Module {
|
|||||||
/// Clear the [`Module`].
|
/// Clear the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.id.clear();
|
self.id = None;
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
self.doc.clear();
|
self.doc.clear();
|
||||||
self.internal = false;
|
self.internal = false;
|
||||||
@ -2078,7 +2080,7 @@ impl Module {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.set_id(ast.source_raw().clone());
|
module.id = ast.source_raw().cloned();
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
module.set_doc(ast.doc());
|
module.set_doc(ast.doc());
|
||||||
|
@ -62,8 +62,8 @@ mod debugging_functions {
|
|||||||
Dynamic::from_array(_args.clone().to_vec()),
|
Dynamic::from_array(_args.clone().to_vec()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !_source.is_empty() {
|
if let Some(source) = _source {
|
||||||
map.insert("source".into(), _source.into());
|
map.insert("source".into(), source.into());
|
||||||
}
|
}
|
||||||
if !_pos.is_none() {
|
if !_pos.is_none() {
|
||||||
map.insert(
|
map.insert(
|
||||||
|
@ -578,7 +578,7 @@ fn test_module_context() -> Result<(), Box<EvalAltResult>> {
|
|||||||
let new_context = NativeCallContext::new_with_all_fields(
|
let new_context = NativeCallContext::new_with_all_fields(
|
||||||
engine,
|
engine,
|
||||||
&fn_name,
|
&fn_name,
|
||||||
source.as_ref().map(|s| s.as_str()),
|
source.as_ref().map(String::as_str),
|
||||||
&global,
|
&global,
|
||||||
&lib,
|
&lib,
|
||||||
pos,
|
pos,
|
||||||
|
@ -89,21 +89,21 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{ast:?}"),
|
format!("{ast:?}"),
|
||||||
r#"AST { source: "", doc: "", resolver: None, body: [Expr(123 @ 1:53)] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [Expr(123 @ 1:53)] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
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: "", doc: "", resolver: None, body: [Var(("DECISION" @ 1:7, false @ 1:18, None), CONSTANT, 1:1), Expr(123 @ 1:51)] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [Var(("DECISION" @ 1:7, false @ 1:18, None), CONSTANT, 1:1), Expr(123 @ 1:51)] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
let ast = engine.compile("if 1 == 2 { 42 }")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{ast:?}"),
|
format!("{ast:?}"),
|
||||||
r#"AST { source: "", doc: "", resolver: None, body: [] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
engine.set_optimization_level(OptimizationLevel::Full);
|
engine.set_optimization_level(OptimizationLevel::Full);
|
||||||
@ -112,14 +112,14 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{ast:?}"),
|
format!("{ast:?}"),
|
||||||
r#"AST { source: "", doc: "", resolver: None, body: [Expr(42 @ 1:1)] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [Expr(42 @ 1:1)] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let ast = engine.compile("NUMBER")?;
|
let ast = engine.compile("NUMBER")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{ast:?}"),
|
format!("{ast:?}"),
|
||||||
r#"AST { source: "", doc: "", resolver: None, body: [Expr(Variable(NUMBER) @ 1:1)] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [Expr(Variable(NUMBER) @ 1:1)] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
@ -131,7 +131,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{ast:?}"),
|
format!("{ast:?}"),
|
||||||
r#"AST { source: "", doc: "", resolver: None, body: [Expr(42 @ 1:1)] }"#
|
r#"AST { source: None, doc: "", resolver: None, body: [Expr(42 @ 1:1)] }"#
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user