Make Engine faster to create.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
use crate::func::native::locked_write;
|
||||
use crate::parser::{ParseResult, ParseState};
|
||||
use crate::types::StringsInterner;
|
||||
use crate::{Engine, OptimizationLevel, Scope, AST};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@@ -126,7 +127,7 @@ impl Engine {
|
||||
let path = path.clone();
|
||||
|
||||
match self
|
||||
.module_resolver
|
||||
.module_resolver()
|
||||
.resolve_ast(self, None, &path, crate::Position::NONE)
|
||||
{
|
||||
Some(Ok(module_ast)) => collect_imports(&module_ast, &resolver, &mut imports),
|
||||
@@ -135,7 +136,7 @@ impl Engine {
|
||||
}
|
||||
|
||||
let module =
|
||||
self.module_resolver
|
||||
self.module_resolver()
|
||||
.resolve(self, None, &path, crate::Position::NONE)?;
|
||||
|
||||
let module = shared_take_or_clone(module);
|
||||
@@ -223,7 +224,17 @@ impl Engine {
|
||||
optimization_level: OptimizationLevel,
|
||||
) -> ParseResult<AST> {
|
||||
let (stream, tc) = self.lex_raw(scripts.as_ref(), self.token_mapper.as_deref());
|
||||
let interned_strings = &mut *locked_write(&self.interned_strings);
|
||||
|
||||
let mut interner;
|
||||
let mut guard;
|
||||
let interned_strings = if let Some(ref interner) = self.interned_strings {
|
||||
guard = locked_write(interner);
|
||||
&mut *guard
|
||||
} else {
|
||||
interner = StringsInterner::new();
|
||||
&mut interner
|
||||
};
|
||||
|
||||
let state = &mut ParseState::new(scope, interned_strings, tc);
|
||||
let mut _ast = self.parse(stream.peekable(), state, optimization_level)?;
|
||||
#[cfg(feature = "metadata")]
|
||||
@@ -294,7 +305,17 @@ impl Engine {
|
||||
) -> ParseResult<AST> {
|
||||
let scripts = [script];
|
||||
let (stream, t) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
||||
let interned_strings = &mut *locked_write(&self.interned_strings);
|
||||
|
||||
let mut interner;
|
||||
let mut guard;
|
||||
let interned_strings = if let Some(ref interner) = self.interned_strings {
|
||||
guard = locked_write(interner);
|
||||
&mut *guard
|
||||
} else {
|
||||
interner = StringsInterner::new();
|
||||
&mut interner
|
||||
};
|
||||
|
||||
let state = &mut ParseState::new(Some(scope), interned_strings, t);
|
||||
self.parse_global_expr(stream.peekable(), state, |_| {}, self.optimization_level)
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ use crate::eval::{Caches, GlobalRuntimeState};
|
||||
use crate::func::native::locked_write;
|
||||
use crate::parser::ParseState;
|
||||
use crate::types::dynamic::Variant;
|
||||
use crate::types::StringsInterner;
|
||||
use crate::{
|
||||
Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR,
|
||||
};
|
||||
@@ -119,7 +120,15 @@ impl Engine {
|
||||
) -> RhaiResultOf<T> {
|
||||
let scripts = [script];
|
||||
let ast = {
|
||||
let interned_strings = &mut *locked_write(&self.interned_strings);
|
||||
let mut interner;
|
||||
let mut guard;
|
||||
let interned_strings = if let Some(ref interner) = self.interned_strings {
|
||||
guard = locked_write(interner);
|
||||
&mut *guard
|
||||
} else {
|
||||
interner = StringsInterner::new();
|
||||
&mut interner
|
||||
};
|
||||
|
||||
let (stream, tc) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
||||
|
||||
|
@@ -286,7 +286,7 @@ impl Engine {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn on_print(&mut self, callback: impl Fn(&str) + SendSync + 'static) -> &mut Self {
|
||||
self.print = Box::new(callback);
|
||||
self.print = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
/// Override default action of `debug` (print to stdout using [`println!`])
|
||||
@@ -336,7 +336,7 @@ impl Engine {
|
||||
&mut self,
|
||||
callback: impl Fn(&str, Option<&str>, Position) + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.debug = Box::new(callback);
|
||||
self.debug = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
/// _(debugging)_ Register a callback for debugging.
|
||||
|
@@ -4,6 +4,7 @@
|
||||
use crate::func::native::locked_write;
|
||||
use crate::parser::{ParseSettingFlags, ParseState};
|
||||
use crate::tokenizer::Token;
|
||||
use crate::types::StringsInterner;
|
||||
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@@ -115,7 +116,16 @@ impl Engine {
|
||||
);
|
||||
|
||||
let ast = {
|
||||
let interned_strings = &mut *locked_write(&self.interned_strings);
|
||||
let mut interner;
|
||||
let mut guard;
|
||||
let interned_strings = if let Some(ref interner) = self.interned_strings {
|
||||
guard = locked_write(interner);
|
||||
&mut *guard
|
||||
} else {
|
||||
interner = StringsInterner::new();
|
||||
&mut interner
|
||||
};
|
||||
|
||||
let state = &mut ParseState::new(None, interned_strings, tokenizer_control);
|
||||
|
||||
self.parse_global_expr(
|
||||
|
@@ -54,7 +54,10 @@ impl Engine {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn module_resolver(&self) -> &dyn crate::ModuleResolver {
|
||||
&*self.module_resolver
|
||||
const DUMMY_RESOLVER: crate::module::resolvers::DummyModuleResolver =
|
||||
crate::module::resolvers::DummyModuleResolver;
|
||||
|
||||
self.module_resolver.as_deref().unwrap_or(&DUMMY_RESOLVER)
|
||||
}
|
||||
|
||||
/// Set the module resolution service used by the [`Engine`].
|
||||
@@ -66,7 +69,7 @@ impl Engine {
|
||||
&mut self,
|
||||
resolver: impl crate::ModuleResolver + 'static,
|
||||
) -> &mut Self {
|
||||
self.module_resolver = Box::new(resolver);
|
||||
self.module_resolver = Some(Box::new(resolver));
|
||||
self
|
||||
}
|
||||
|
||||
|
@@ -38,24 +38,26 @@ impl LangOptions {
|
||||
/// Create a new [`LangOptions`] with default values.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::IF_EXPR
|
||||
| Self::SWITCH_EXPR
|
||||
| Self::LOOP_EXPR
|
||||
| Self::STMT_EXPR
|
||||
| Self::LOOPING
|
||||
| Self::SHADOWING
|
||||
| Self::FAST_OPS
|
||||
| {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
{
|
||||
Self::ANON_FN
|
||||
}
|
||||
#[cfg(feature = "no_function")]
|
||||
{
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
pub const fn new() -> Self {
|
||||
Self::from_bits_truncate(
|
||||
Self::IF_EXPR.bits()
|
||||
| Self::SWITCH_EXPR.bits()
|
||||
| Self::LOOP_EXPR.bits()
|
||||
| Self::STMT_EXPR.bits()
|
||||
| Self::LOOPING.bits()
|
||||
| Self::SHADOWING.bits()
|
||||
| Self::FAST_OPS.bits()
|
||||
| {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
{
|
||||
Self::ANON_FN.bits()
|
||||
}
|
||||
#[cfg(feature = "no_function")]
|
||||
{
|
||||
Self::empty().bits()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
//! Module that defines the public function/module registration API of [`Engine`].
|
||||
|
||||
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
||||
use crate::module::ModuleFlags;
|
||||
use crate::types::dynamic::Variant;
|
||||
use crate::{
|
||||
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
|
||||
@@ -14,20 +15,18 @@ use std::prelude::v1::*;
|
||||
use crate::func::register::Mut;
|
||||
|
||||
impl Engine {
|
||||
/// Get the global namespace module (which is the fist module in `global_modules`).
|
||||
#[inline(always)]
|
||||
#[allow(dead_code)]
|
||||
#[must_use]
|
||||
pub(crate) fn global_namespace(&self) -> &Module {
|
||||
self.global_modules.first().unwrap()
|
||||
}
|
||||
/// Get a mutable reference to the global namespace module
|
||||
/// (which is the first module in `global_modules`).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub(crate) fn global_namespace_mut(&mut self) -> &mut Module {
|
||||
let module = self.global_modules.first_mut().unwrap();
|
||||
Shared::get_mut(module).expect("not shared")
|
||||
fn global_namespace_mut(&mut self) -> &mut Module {
|
||||
if self.global_modules.is_empty() {
|
||||
let mut global_namespace = Module::new();
|
||||
global_namespace.flags |= ModuleFlags::INTERNAL;
|
||||
self.global_modules.push(global_namespace.into());
|
||||
}
|
||||
|
||||
Shared::get_mut(self.global_modules.first_mut().unwrap()).expect("not shared")
|
||||
}
|
||||
/// Register a custom function with the [`Engine`].
|
||||
///
|
||||
@@ -677,6 +676,9 @@ impl Engine {
|
||||
/// modules are searched in reverse order.
|
||||
#[inline(always)]
|
||||
pub fn register_global_module(&mut self, module: SharedModule) -> &mut Self {
|
||||
// Make sure the global namespace is created.
|
||||
let _ = self.global_namespace_mut();
|
||||
|
||||
// Insert the module into the front.
|
||||
// The first module is always the global namespace.
|
||||
self.global_modules.insert(1, module);
|
||||
@@ -779,7 +781,9 @@ impl Engine {
|
||||
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
|
||||
let mut signatures = Vec::with_capacity(64);
|
||||
|
||||
signatures.extend(self.global_namespace().gen_fn_signatures());
|
||||
if let Some(global_namespace) = self.global_modules.first() {
|
||||
signatures.extend(global_namespace.gen_fn_signatures());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
for (name, m) in self.global_sub_modules.as_deref().into_iter().flatten() {
|
||||
|
@@ -3,6 +3,7 @@
|
||||
use crate::eval::{Caches, GlobalRuntimeState};
|
||||
use crate::func::native::locked_write;
|
||||
use crate::parser::ParseState;
|
||||
use crate::types::StringsInterner;
|
||||
use crate::{Engine, RhaiResultOf, Scope, AST};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
@@ -59,7 +60,17 @@ impl Engine {
|
||||
let scripts = [script];
|
||||
let ast = {
|
||||
let (stream, tc) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
||||
let interned_strings = &mut *locked_write(&self.interned_strings);
|
||||
|
||||
let mut interner;
|
||||
let mut guard;
|
||||
let interned_strings = if let Some(ref interner) = self.interned_strings {
|
||||
guard = locked_write(interner);
|
||||
&mut *guard
|
||||
} else {
|
||||
interner = StringsInterner::new();
|
||||
&mut interner
|
||||
};
|
||||
|
||||
let state = &mut ParseState::new(Some(scope), interned_strings, tc);
|
||||
self.parse(stream.peekable(), state, self.optimization_level)?
|
||||
};
|
||||
|
Reference in New Issue
Block a user