Simplify lifetimes.
This commit is contained in:
parent
ed568a9395
commit
ade290da7e
@ -21,6 +21,7 @@ Breaking changes
|
||||
* `Module::update_fn_metadata` input parameter is changed.
|
||||
* Function keywords (e.g. `type_of`, `eval`, `Fn`) can no longer be overloaded. It is more trouble than worth. To disable these keywords, use `Engine::disable_symbol`.
|
||||
* `is_def_var` and `is_def_fn` are now reserved keywords.
|
||||
* `Engine::id` field is removed.
|
||||
|
||||
Enhancements
|
||||
------------
|
||||
|
@ -525,18 +525,6 @@ impl State {
|
||||
pub fn is_global(&self) -> bool {
|
||||
self.scope_level == 0
|
||||
}
|
||||
/// Get the current functions resolution cache.
|
||||
pub fn fn_resolution_cache(
|
||||
&self,
|
||||
) -> Option<
|
||||
&HashMap<
|
||||
NonZeroU64,
|
||||
Option<(CallableFunction, Option<ImmutableString>)>,
|
||||
StraightHasherBuilder,
|
||||
>,
|
||||
> {
|
||||
self.fn_resolution_caches.last()
|
||||
}
|
||||
/// Get a mutable reference to the current functions resolution cache.
|
||||
pub fn fn_resolution_cache_mut(
|
||||
&mut self,
|
||||
@ -617,17 +605,17 @@ pub struct Limits {
|
||||
|
||||
/// Context of a script evaluation process.
|
||||
#[derive(Debug)]
|
||||
pub struct EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> {
|
||||
pub(crate) engine: &'e Engine,
|
||||
pub struct EvalContext<'a, 'x, 'px, 'm, 's, 't, 'pt> {
|
||||
pub(crate) engine: &'a Engine,
|
||||
pub(crate) scope: &'x mut Scope<'px>,
|
||||
pub(crate) mods: &'a mut Imports,
|
||||
pub(crate) mods: &'m mut Imports,
|
||||
pub(crate) state: &'s mut State,
|
||||
pub(crate) lib: &'m [&'m Module],
|
||||
pub(crate) lib: &'a [&'a Module],
|
||||
pub(crate) this_ptr: &'t mut Option<&'pt mut Dynamic>,
|
||||
pub(crate) level: usize,
|
||||
}
|
||||
|
||||
impl<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> {
|
||||
impl<'x, 'px> EvalContext<'_, 'x, 'px, '_, '_, '_, '_> {
|
||||
/// The current [`Engine`].
|
||||
#[inline(always)]
|
||||
pub fn engine(&self) -> &Engine {
|
||||
@ -710,9 +698,6 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 't,
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Engine {
|
||||
/// A unique ID identifying this scripting [`Engine`].
|
||||
pub id: String,
|
||||
|
||||
/// A module containing all functions directly loaded into the Engine.
|
||||
pub(crate) global_namespace: Module,
|
||||
/// A collection of all modules loaded into the global namespace of the Engine.
|
||||
@ -757,12 +742,8 @@ pub struct Engine {
|
||||
impl fmt::Debug for Engine {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if !self.id.is_empty() {
|
||||
write!(f, "Engine({})", self.id)
|
||||
} else {
|
||||
f.write_str("Engine")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Engine {
|
||||
@ -819,8 +800,6 @@ impl Engine {
|
||||
pub fn new() -> Self {
|
||||
// Create the new scripting Engine
|
||||
let mut engine = Self {
|
||||
id: Default::default(),
|
||||
|
||||
global_namespace: Default::default(),
|
||||
global_modules: Default::default(),
|
||||
global_sub_modules: Default::default(),
|
||||
@ -886,8 +865,6 @@ impl Engine {
|
||||
#[inline]
|
||||
pub fn new_raw() -> Self {
|
||||
Self {
|
||||
id: Default::default(),
|
||||
|
||||
global_namespace: Default::default(),
|
||||
global_modules: Default::default(),
|
||||
global_sub_modules: Default::default(),
|
||||
@ -934,14 +911,13 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Search for a module within an imports stack.
|
||||
/// [`Position`] in [`EvalAltResult`] is [`NONE`][Position::NONE] and must be set afterwards.
|
||||
pub fn search_imports(
|
||||
pub(crate) fn search_imports(
|
||||
&self,
|
||||
mods: &Imports,
|
||||
state: &mut State,
|
||||
namespace: &NamespaceRef,
|
||||
) -> Result<Shared<Module>, Box<EvalAltResult>> {
|
||||
let Ident { name: root, pos } = &namespace[0];
|
||||
) -> Option<Shared<Module>> {
|
||||
let root = &namespace[0].name;
|
||||
|
||||
// Qualified - check if the root module is directly indexed
|
||||
let index = if state.always_search {
|
||||
@ -950,15 +926,14 @@ impl Engine {
|
||||
namespace.index()
|
||||
};
|
||||
|
||||
Ok(if let Some(index) = index {
|
||||
if let Some(index) = index {
|
||||
let offset = mods.len() - index.get();
|
||||
mods.get(offset).expect("invalid index in Imports")
|
||||
Some(mods.get(offset).expect("invalid index in Imports"))
|
||||
} else {
|
||||
mods.find(root)
|
||||
.map(|n| mods.get(n).expect("invalid index in Imports"))
|
||||
.or_else(|| self.global_sub_modules.get(root).cloned())
|
||||
.ok_or_else(|| EvalAltResult::ErrorModuleNotFound(root.to_string(), *pos))?
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for a variable within the scope or within imports,
|
||||
@ -976,7 +951,12 @@ impl Engine {
|
||||
Expr::Variable(v) => match v.as_ref() {
|
||||
// Qualified variable
|
||||
(_, Some((hash_var, modules)), Ident { name, pos }) => {
|
||||
let module = self.search_imports(mods, state, modules)?;
|
||||
let module = self.search_imports(mods, state, modules).ok_or_else(|| {
|
||||
EvalAltResult::ErrorModuleNotFound(
|
||||
modules[0].name.to_string(),
|
||||
modules[0].pos,
|
||||
)
|
||||
})?;
|
||||
let target = module.get_qualified_var(*hash_var).map_err(|mut err| {
|
||||
match *err {
|
||||
EvalAltResult::ErrorVariableNotFound(ref mut err_name, _) => {
|
||||
@ -1068,7 +1048,7 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Chain-evaluate a dot/index chain.
|
||||
/// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards.
|
||||
/// [`Position`] in [`EvalAltResult`] is [`NONE`][Position::NONE] and must be set afterwards.
|
||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||
fn eval_dot_index_chain_helper(
|
||||
&self,
|
||||
|
@ -1028,7 +1028,7 @@ impl Engine {
|
||||
scripts: &[&str],
|
||||
optimization_level: OptimizationLevel,
|
||||
) -> Result<AST, ParseError> {
|
||||
let stream = self.lex(scripts);
|
||||
let stream = self.lex_raw(scripts, None);
|
||||
self.parse(&mut stream.peekable(), scope, optimization_level)
|
||||
}
|
||||
/// Read the contents of a file into a string.
|
||||
@ -1190,9 +1190,9 @@ impl Engine {
|
||||
.into());
|
||||
};
|
||||
|
||||
let stream = self.lex_with_map(
|
||||
let stream = self.lex_raw(
|
||||
&scripts,
|
||||
if has_null {
|
||||
Some(if has_null {
|
||||
|token| match token {
|
||||
// If `null` is present, make sure `null` is treated as a variable
|
||||
Token::Reserved(s) if s == "null" => Token::Identifier(s),
|
||||
@ -1200,7 +1200,7 @@ impl Engine {
|
||||
}
|
||||
} else {
|
||||
|t| t
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
let ast =
|
||||
@ -1283,7 +1283,7 @@ impl Engine {
|
||||
script: &str,
|
||||
) -> Result<AST, ParseError> {
|
||||
let scripts = [script];
|
||||
let stream = self.lex(&scripts);
|
||||
let stream = self.lex_raw(&scripts, None);
|
||||
|
||||
let mut peekable = stream.peekable();
|
||||
self.parse_global_expr(&mut peekable, scope, self.optimization_level)
|
||||
@ -1444,7 +1444,7 @@ impl Engine {
|
||||
script: &str,
|
||||
) -> Result<T, Box<EvalAltResult>> {
|
||||
let scripts = [script];
|
||||
let stream = self.lex(&scripts);
|
||||
let stream = self.lex_raw(&scripts, None);
|
||||
|
||||
// No need to optimize a lone expression
|
||||
let ast = self.parse_global_expr(&mut stream.peekable(), scope, OptimizationLevel::None)?;
|
||||
@ -1585,7 +1585,7 @@ impl Engine {
|
||||
script: &str,
|
||||
) -> Result<(), Box<EvalAltResult>> {
|
||||
let scripts = [script];
|
||||
let stream = self.lex(&scripts);
|
||||
let stream = self.lex_raw(&scripts, None);
|
||||
let ast = self.parse(&mut stream.peekable(), scope, self.optimization_level)?;
|
||||
self.consume_ast_with_scope(scope, &ast)
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ impl Engine {
|
||||
/// # Examples
|
||||
///
|
||||
/// The following will raise an error during parsing because the `if` keyword is disabled
|
||||
/// and is recognized as a variable name!
|
||||
/// and is recognized as a reserved symbol!
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// # fn main() -> Result<(), rhai::ParseError> {
|
||||
@ -214,7 +214,7 @@ impl Engine {
|
||||
/// engine.disable_symbol("if"); // disable the 'if' keyword
|
||||
///
|
||||
/// engine.compile("let x = if true { 42 } else { 0 };")?;
|
||||
/// // ^ 'if' is rejected as a reserved keyword
|
||||
/// // ^ 'if' is rejected as a reserved symbol
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
|
@ -1357,7 +1357,9 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
let module = self.search_imports(mods, state, namespace)?;
|
||||
let module = self.search_imports(mods, state, namespace).ok_or_else(|| {
|
||||
EvalAltResult::ErrorModuleNotFound(namespace[0].name.to_string(), namespace[0].pos)
|
||||
})?;
|
||||
|
||||
// First search in script-defined functions (can override built-in)
|
||||
let func = match module.get_qualified_fn(hash_script) {
|
||||
|
@ -55,20 +55,19 @@ pub type Locked<T> = crate::stdlib::sync::RwLock<T>;
|
||||
|
||||
/// Context of a native Rust function call.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct NativeCallContext<'e, 'n, 's, 'a, 'm> {
|
||||
engine: &'e Engine,
|
||||
fn_name: &'n str,
|
||||
source: Option<&'s str>,
|
||||
pub(crate) mods: Option<&'a Imports>,
|
||||
pub(crate) lib: &'m [&'m Module],
|
||||
pub struct NativeCallContext<'a> {
|
||||
engine: &'a Engine,
|
||||
fn_name: &'a str,
|
||||
source: Option<&'a str>,
|
||||
mods: Option<&'a Imports>,
|
||||
lib: &'a [&'a Module],
|
||||
}
|
||||
|
||||
impl<'e, 'n, 's, 'a, 'm, M: AsRef<[&'m Module]> + ?Sized>
|
||||
From<(&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)>
|
||||
for NativeCallContext<'e, 'n, 's, 'a, 'm>
|
||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized>
|
||||
From<(&'a Engine, &'a str, Option<&'a str>, &'a Imports, &'a M)> for NativeCallContext<'a>
|
||||
{
|
||||
#[inline(always)]
|
||||
fn from(value: (&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)) -> Self {
|
||||
fn from(value: (&'a Engine, &'a str, Option<&'a str>, &'a Imports, &'a M)) -> Self {
|
||||
Self {
|
||||
engine: value.0,
|
||||
fn_name: value.1,
|
||||
@ -79,11 +78,11 @@ impl<'e, 'n, 's, 'a, 'm, M: AsRef<[&'m Module]> + ?Sized>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e, 'n, 'm, M: AsRef<[&'m Module]> + ?Sized> From<(&'e Engine, &'n str, &'m M)>
|
||||
for NativeCallContext<'e, 'n, '_, '_, 'm>
|
||||
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M)>
|
||||
for NativeCallContext<'a>
|
||||
{
|
||||
#[inline(always)]
|
||||
fn from(value: (&'e Engine, &'n str, &'m M)) -> Self {
|
||||
fn from(value: (&'a Engine, &'a str, &'a M)) -> Self {
|
||||
Self {
|
||||
engine: value.0,
|
||||
fn_name: value.1,
|
||||
@ -94,10 +93,10 @@ impl<'e, 'n, 'm, M: AsRef<[&'m Module]> + ?Sized> From<(&'e Engine, &'n str, &'m
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e, 'n, 's, 'a, 'm> NativeCallContext<'e, 'n, 's, 'a, 'm> {
|
||||
impl<'a> NativeCallContext<'a> {
|
||||
/// Create a new [`NativeCallContext`].
|
||||
#[inline(always)]
|
||||
pub fn new(engine: &'e Engine, fn_name: &'n str, lib: &'m [&'m Module]) -> Self {
|
||||
pub fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self {
|
||||
Self {
|
||||
engine,
|
||||
fn_name,
|
||||
@ -112,11 +111,11 @@ impl<'e, 'n, 's, 'a, 'm> NativeCallContext<'e, 'n, 's, 'a, 'm> {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline(always)]
|
||||
pub fn new_with_all_fields(
|
||||
engine: &'e Engine,
|
||||
fn_name: &'n str,
|
||||
source: &'s Option<&str>,
|
||||
imports: &'a mut Imports,
|
||||
lib: &'m [&'m Module],
|
||||
engine: &'a Engine,
|
||||
fn_name: &'a str,
|
||||
source: &'a Option<&str>,
|
||||
imports: &'a Imports,
|
||||
lib: &'a [&Module],
|
||||
) -> Self {
|
||||
Self {
|
||||
engine,
|
||||
@ -147,6 +146,14 @@ impl<'e, 'n, 's, 'a, 'm> NativeCallContext<'e, 'n, 's, 'a, 'm> {
|
||||
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||
self.mods.iter().flat_map(|&m| m.iter())
|
||||
}
|
||||
/// Get an iterator over the current set of modules imported via `import` statements.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_imports_raw(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> {
|
||||
self.mods.iter().flat_map(|&m| m.iter_raw())
|
||||
}
|
||||
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
|
||||
/// Available under the `internals` feature only.
|
||||
#[cfg(feature = "internals")]
|
||||
|
@ -110,15 +110,13 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> Array {
|
||||
|
||||
let mut list: Array = Default::default();
|
||||
|
||||
ctx.lib
|
||||
.iter()
|
||||
ctx.iter_namespaces()
|
||||
.flat_map(|m| m.iter_script_fn())
|
||||
.for_each(|(_, _, _, _, f)| list.push(make_metadata(&dict, None, f).into()));
|
||||
|
||||
if let Some(mods) = ctx.mods {
|
||||
mods.iter_raw()
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
ctx.iter_imports_raw()
|
||||
.for_each(|(ns, m)| scan_module(&mut list, &dict, ns.clone(), m.as_ref()));
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ impl Expression<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
|
||||
impl EvalContext<'_, '_, '_, '_, '_, '_, '_> {
|
||||
/// Evaluate an [expression tree][Expression].
|
||||
///
|
||||
/// # WARNING - Low Level API
|
||||
|
33
src/token.rs
33
src/token.rs
@ -30,7 +30,7 @@ type LERR = LexError;
|
||||
const NUM_SEP: char = '_';
|
||||
|
||||
/// A stream of tokens.
|
||||
pub type TokenStream<'a, 't> = Peekable<TokenIterator<'a, 't>>;
|
||||
pub type TokenStream<'a> = Peekable<TokenIterator<'a>>;
|
||||
|
||||
/// A location (line number + character position) in the input script.
|
||||
///
|
||||
@ -1741,9 +1741,9 @@ impl InputStream for MultiInputsStream<'_> {
|
||||
}
|
||||
|
||||
/// An iterator on a [`Token`] stream.
|
||||
pub struct TokenIterator<'a, 'e> {
|
||||
pub struct TokenIterator<'a> {
|
||||
/// Reference to the scripting `Engine`.
|
||||
engine: &'e Engine,
|
||||
engine: &'a Engine,
|
||||
/// Current state.
|
||||
state: TokenizeState,
|
||||
/// Current position.
|
||||
@ -1754,7 +1754,7 @@ pub struct TokenIterator<'a, 'e> {
|
||||
map: Option<fn(Token) -> Token>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TokenIterator<'a, '_> {
|
||||
impl<'a> Iterator for TokenIterator<'a> {
|
||||
type Item = (Token, Position);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -1837,30 +1837,31 @@ impl<'a> Iterator for TokenIterator<'a, '_> {
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
/// Tokenize an input text stream.
|
||||
/// _(INTERNALS)_ Tokenize an input text stream.
|
||||
/// Exported under the `internals` feature only.
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
pub fn lex<'a, 'e>(
|
||||
&'e self,
|
||||
input: impl IntoIterator<Item = &'a &'a str>,
|
||||
) -> TokenIterator<'a, 'e> {
|
||||
pub fn lex<'a>(&'a self, input: impl IntoIterator<Item = &'a &'a str>) -> TokenIterator<'a> {
|
||||
self.lex_raw(input, None)
|
||||
}
|
||||
/// Tokenize an input text stream with a mapping function.
|
||||
/// _(INTERNALS)_ Tokenize an input text stream with a mapping function.
|
||||
/// Exported under the `internals` feature only.
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
pub fn lex_with_map<'a, 'e>(
|
||||
&'e self,
|
||||
pub fn lex_with_map<'a>(
|
||||
&'a self,
|
||||
input: impl IntoIterator<Item = &'a &'a str>,
|
||||
map: fn(Token) -> Token,
|
||||
) -> TokenIterator<'a, 'e> {
|
||||
) -> TokenIterator<'a> {
|
||||
self.lex_raw(input, Some(map))
|
||||
}
|
||||
/// Tokenize an input text stream with an optional mapping function.
|
||||
#[inline]
|
||||
fn lex_raw<'a, 'e>(
|
||||
&'e self,
|
||||
pub(crate) fn lex_raw<'a>(
|
||||
&'a self,
|
||||
input: impl IntoIterator<Item = &'a &'a str>,
|
||||
map: Option<fn(Token) -> Token>,
|
||||
) -> TokenIterator<'a, 'e> {
|
||||
) -> TokenIterator<'a> {
|
||||
TokenIterator {
|
||||
engine: self,
|
||||
state: TokenizeState {
|
||||
|
Loading…
Reference in New Issue
Block a user