Make Engine faster to create.
This commit is contained in:
parent
c2a8c342bb
commit
51581cdef5
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::func::native::locked_write;
|
use crate::func::native::locked_write;
|
||||||
use crate::parser::{ParseResult, ParseState};
|
use crate::parser::{ParseResult, ParseState};
|
||||||
|
use crate::types::StringsInterner;
|
||||||
use crate::{Engine, OptimizationLevel, Scope, AST};
|
use crate::{Engine, OptimizationLevel, Scope, AST};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -126,7 +127,7 @@ impl Engine {
|
|||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
|
|
||||||
match self
|
match self
|
||||||
.module_resolver
|
.module_resolver()
|
||||||
.resolve_ast(self, None, &path, crate::Position::NONE)
|
.resolve_ast(self, None, &path, crate::Position::NONE)
|
||||||
{
|
{
|
||||||
Some(Ok(module_ast)) => collect_imports(&module_ast, &resolver, &mut imports),
|
Some(Ok(module_ast)) => collect_imports(&module_ast, &resolver, &mut imports),
|
||||||
@ -135,7 +136,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let module =
|
let module =
|
||||||
self.module_resolver
|
self.module_resolver()
|
||||||
.resolve(self, None, &path, crate::Position::NONE)?;
|
.resolve(self, None, &path, crate::Position::NONE)?;
|
||||||
|
|
||||||
let module = shared_take_or_clone(module);
|
let module = shared_take_or_clone(module);
|
||||||
@ -223,7 +224,17 @@ impl Engine {
|
|||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> ParseResult<AST> {
|
) -> ParseResult<AST> {
|
||||||
let (stream, tc) = self.lex_raw(scripts.as_ref(), self.token_mapper.as_deref());
|
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 state = &mut ParseState::new(scope, interned_strings, tc);
|
||||||
let mut _ast = self.parse(stream.peekable(), state, optimization_level)?;
|
let mut _ast = self.parse(stream.peekable(), state, optimization_level)?;
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
@ -294,7 +305,17 @@ impl Engine {
|
|||||||
) -> ParseResult<AST> {
|
) -> ParseResult<AST> {
|
||||||
let scripts = [script];
|
let scripts = [script];
|
||||||
let (stream, t) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
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);
|
let state = &mut ParseState::new(Some(scope), interned_strings, t);
|
||||||
self.parse_global_expr(stream.peekable(), state, |_| {}, self.optimization_level)
|
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::func::native::locked_write;
|
||||||
use crate::parser::ParseState;
|
use crate::parser::ParseState;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
|
use crate::types::StringsInterner;
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR,
|
Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR,
|
||||||
};
|
};
|
||||||
@ -119,7 +120,15 @@ impl Engine {
|
|||||||
) -> RhaiResultOf<T> {
|
) -> RhaiResultOf<T> {
|
||||||
let scripts = [script];
|
let scripts = [script];
|
||||||
let ast = {
|
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());
|
let (stream, tc) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ impl Engine {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn on_print(&mut self, callback: impl Fn(&str) + SendSync + 'static) -> &mut Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
/// Override default action of `debug` (print to stdout using [`println!`])
|
/// Override default action of `debug` (print to stdout using [`println!`])
|
||||||
@ -336,7 +336,7 @@ impl Engine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
callback: impl Fn(&str, Option<&str>, Position) + SendSync + 'static,
|
callback: impl Fn(&str, Option<&str>, Position) + SendSync + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.debug = Box::new(callback);
|
self.debug = Some(Box::new(callback));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// _(debugging)_ Register a callback for debugging.
|
/// _(debugging)_ Register a callback for debugging.
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
use crate::func::native::locked_write;
|
use crate::func::native::locked_write;
|
||||||
use crate::parser::{ParseSettingFlags, ParseState};
|
use crate::parser::{ParseSettingFlags, ParseState};
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
|
use crate::types::StringsInterner;
|
||||||
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf};
|
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -115,7 +116,16 @@ impl Engine {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let ast = {
|
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);
|
let state = &mut ParseState::new(None, interned_strings, tokenizer_control);
|
||||||
|
|
||||||
self.parse_global_expr(
|
self.parse_global_expr(
|
||||||
|
@ -54,7 +54,10 @@ impl Engine {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn module_resolver(&self) -> &dyn crate::ModuleResolver {
|
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`].
|
/// Set the module resolution service used by the [`Engine`].
|
||||||
@ -66,7 +69,7 @@ impl Engine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
resolver: impl crate::ModuleResolver + 'static,
|
resolver: impl crate::ModuleResolver + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.module_resolver = Box::new(resolver);
|
self.module_resolver = Some(Box::new(resolver));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,24 +38,26 @@ impl LangOptions {
|
|||||||
/// Create a new [`LangOptions`] with default values.
|
/// Create a new [`LangOptions`] with default values.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self::IF_EXPR
|
Self::from_bits_truncate(
|
||||||
| Self::SWITCH_EXPR
|
Self::IF_EXPR.bits()
|
||||||
| Self::LOOP_EXPR
|
| Self::SWITCH_EXPR.bits()
|
||||||
| Self::STMT_EXPR
|
| Self::LOOP_EXPR.bits()
|
||||||
| Self::LOOPING
|
| Self::STMT_EXPR.bits()
|
||||||
| Self::SHADOWING
|
| Self::LOOPING.bits()
|
||||||
| Self::FAST_OPS
|
| Self::SHADOWING.bits()
|
||||||
| {
|
| Self::FAST_OPS.bits()
|
||||||
#[cfg(not(feature = "no_function"))]
|
| {
|
||||||
{
|
#[cfg(not(feature = "no_function"))]
|
||||||
Self::ANON_FN
|
{
|
||||||
}
|
Self::ANON_FN.bits()
|
||||||
#[cfg(feature = "no_function")]
|
}
|
||||||
{
|
#[cfg(feature = "no_function")]
|
||||||
Self::empty()
|
{
|
||||||
}
|
Self::empty().bits()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Module that defines the public function/module registration API of [`Engine`].
|
//! Module that defines the public function/module registration API of [`Engine`].
|
||||||
|
|
||||||
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
|
||||||
|
use crate::module::ModuleFlags;
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{
|
use crate::{
|
||||||
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
|
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
|
||||||
@ -14,20 +15,18 @@ use std::prelude::v1::*;
|
|||||||
use crate::func::register::Mut;
|
use crate::func::register::Mut;
|
||||||
|
|
||||||
impl Engine {
|
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
|
/// Get a mutable reference to the global namespace module
|
||||||
/// (which is the first module in `global_modules`).
|
/// (which is the first module in `global_modules`).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn global_namespace_mut(&mut self) -> &mut Module {
|
fn global_namespace_mut(&mut self) -> &mut Module {
|
||||||
let module = self.global_modules.first_mut().unwrap();
|
if self.global_modules.is_empty() {
|
||||||
Shared::get_mut(module).expect("not shared")
|
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`].
|
/// Register a custom function with the [`Engine`].
|
||||||
///
|
///
|
||||||
@ -677,6 +676,9 @@ impl Engine {
|
|||||||
/// modules are searched in reverse order.
|
/// modules are searched in reverse order.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_global_module(&mut self, module: SharedModule) -> &mut Self {
|
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.
|
// Insert the module into the front.
|
||||||
// The first module is always the global namespace.
|
// The first module is always the global namespace.
|
||||||
self.global_modules.insert(1, module);
|
self.global_modules.insert(1, module);
|
||||||
@ -779,7 +781,9 @@ impl Engine {
|
|||||||
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
|
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
|
||||||
let mut signatures = Vec::with_capacity(64);
|
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"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
for (name, m) in self.global_sub_modules.as_deref().into_iter().flatten() {
|
for (name, m) in self.global_sub_modules.as_deref().into_iter().flatten() {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use crate::eval::{Caches, GlobalRuntimeState};
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::func::native::locked_write;
|
use crate::func::native::locked_write;
|
||||||
use crate::parser::ParseState;
|
use crate::parser::ParseState;
|
||||||
|
use crate::types::StringsInterner;
|
||||||
use crate::{Engine, RhaiResultOf, Scope, AST};
|
use crate::{Engine, RhaiResultOf, Scope, AST};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -59,7 +60,17 @@ impl Engine {
|
|||||||
let scripts = [script];
|
let scripts = [script];
|
||||||
let ast = {
|
let ast = {
|
||||||
let (stream, tc) = self.lex_raw(&scripts, self.token_mapper.as_deref());
|
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);
|
let state = &mut ParseState::new(Some(scope), interned_strings, tc);
|
||||||
self.parse(stream.peekable(), state, self.optimization_level)?
|
self.parse(stream.peekable(), state, self.optimization_level)?
|
||||||
};
|
};
|
||||||
|
125
src/engine.rs
125
src/engine.rs
@ -5,13 +5,11 @@ use crate::func::native::{
|
|||||||
locked_write, OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback,
|
locked_write, OnDebugCallback, OnDefVarCallback, OnParseTokenCallback, OnPrintCallback,
|
||||||
OnVarCallback,
|
OnVarCallback,
|
||||||
};
|
};
|
||||||
use crate::module::ModuleFlags;
|
|
||||||
use crate::packages::{Package, StandardPackage};
|
use crate::packages::{Package, StandardPackage};
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::StringsInterner;
|
use crate::types::StringsInterner;
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, Identifier, ImmutableString, Locked, Module, OptimizationLevel, SharedModule,
|
Dynamic, Identifier, ImmutableString, Locked, OptimizationLevel, SharedModule, StaticVec,
|
||||||
StaticVec,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -103,10 +101,10 @@ pub struct Engine {
|
|||||||
|
|
||||||
/// A module resolution service.
|
/// A module resolution service.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub(crate) module_resolver: Box<dyn crate::ModuleResolver>,
|
pub(crate) module_resolver: Option<Box<dyn crate::ModuleResolver>>,
|
||||||
|
|
||||||
/// Strings interner.
|
/// Strings interner.
|
||||||
pub(crate) interned_strings: Locked<StringsInterner>,
|
pub(crate) interned_strings: Option<Box<Locked<StringsInterner>>>,
|
||||||
|
|
||||||
/// A set of symbols to disable.
|
/// A set of symbols to disable.
|
||||||
pub(crate) disabled_symbols: Option<Box<BTreeSet<Identifier>>>,
|
pub(crate) disabled_symbols: Option<Box<BTreeSet<Identifier>>>,
|
||||||
@ -127,9 +125,9 @@ pub struct Engine {
|
|||||||
pub(crate) token_mapper: Option<Box<OnParseTokenCallback>>,
|
pub(crate) token_mapper: Option<Box<OnParseTokenCallback>>,
|
||||||
|
|
||||||
/// Callback closure for implementing the `print` command.
|
/// Callback closure for implementing the `print` command.
|
||||||
pub(crate) print: Box<OnPrintCallback>,
|
pub(crate) print: Option<Box<OnPrintCallback>>,
|
||||||
/// Callback closure for implementing the `debug` command.
|
/// Callback closure for implementing the `debug` command.
|
||||||
pub(crate) debug: Box<OnDebugCallback>,
|
pub(crate) debug: Option<Box<OnDebugCallback>>,
|
||||||
/// Callback closure for progress reporting.
|
/// Callback closure for progress reporting.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
pub(crate) progress: Option<Box<crate::func::native::OnProgressCallback>>,
|
pub(crate) progress: Option<Box<crate::func::native::OnProgressCallback>>,
|
||||||
@ -231,6 +229,49 @@ pub fn make_setter(id: &str) -> Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
|
/// An empty [`Engine`].
|
||||||
|
pub const EMPTY: Self = Self {
|
||||||
|
global_modules: StaticVec::new_const(),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
global_sub_modules: None,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
module_resolver: None,
|
||||||
|
|
||||||
|
interned_strings: None,
|
||||||
|
disabled_symbols: None,
|
||||||
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
|
custom_keywords: None,
|
||||||
|
#[cfg(not(feature = "no_custom_syntax"))]
|
||||||
|
custom_syntax: None,
|
||||||
|
|
||||||
|
def_var_filter: None,
|
||||||
|
resolve_var: None,
|
||||||
|
token_mapper: None,
|
||||||
|
|
||||||
|
print: None,
|
||||||
|
debug: None,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
progress: None,
|
||||||
|
|
||||||
|
options: LangOptions::new(),
|
||||||
|
|
||||||
|
def_tag: Dynamic::UNIT,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
|
optimization_level: OptimizationLevel::Simple,
|
||||||
|
#[cfg(feature = "no_optimize")]
|
||||||
|
optimization_level: (),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
limits: crate::api::limits::Limits::new(),
|
||||||
|
|
||||||
|
#[cfg(feature = "debugging")]
|
||||||
|
debugger_interface: None,
|
||||||
|
};
|
||||||
|
|
||||||
/// Create a new [`Engine`].
|
/// Create a new [`Engine`].
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -242,22 +283,25 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
{
|
{
|
||||||
engine.module_resolver = Box::new(crate::module::resolvers::FileModuleResolver::new());
|
engine.module_resolver =
|
||||||
|
Some(Box::new(crate::module::resolvers::FileModuleResolver::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine.interned_strings = Some(Locked::new(StringsInterner::new()).into());
|
||||||
|
|
||||||
// default print/debug implementations
|
// default print/debug implementations
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
{
|
{
|
||||||
engine.print = Box::new(|s| println!("{s}"));
|
engine.print = Some(Box::new(|s| println!("{s}")));
|
||||||
engine.debug = Box::new(|s, source, pos| match (source, pos) {
|
engine.debug = Some(Box::new(|s, source, pos| match (source, pos) {
|
||||||
(Some(source), crate::Position::NONE) => println!("{source} | {s}"),
|
(Some(source), crate::Position::NONE) => println!("{source} | {s}"),
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
(Some(source), pos) => println!("{source} @ {pos:?} | {s}"),
|
(Some(source), pos) => println!("{source} @ {pos:?} | {s}"),
|
||||||
(None, crate::Position::NONE) => println!("{s}"),
|
(None, crate::Position::NONE) => println!("{s}"),
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
(None, pos) => println!("{pos:?} | {s}"),
|
(None, pos) => println!("{pos:?} | {s}"),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.register_global_module(StandardPackage::new().as_shared_module());
|
engine.register_global_module(StandardPackage::new().as_shared_module());
|
||||||
@ -270,55 +314,8 @@ impl Engine {
|
|||||||
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
|
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_raw() -> Self {
|
pub const fn new_raw() -> Self {
|
||||||
let mut engine = Self {
|
Self::EMPTY
|
||||||
global_modules: StaticVec::new_const(),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
global_sub_modules: None,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
|
||||||
module_resolver: Box::new(crate::module::resolvers::DummyModuleResolver::new()),
|
|
||||||
|
|
||||||
interned_strings: StringsInterner::new().into(),
|
|
||||||
disabled_symbols: None,
|
|
||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
|
||||||
custom_keywords: None,
|
|
||||||
#[cfg(not(feature = "no_custom_syntax"))]
|
|
||||||
custom_syntax: None,
|
|
||||||
|
|
||||||
def_var_filter: None,
|
|
||||||
resolve_var: None,
|
|
||||||
token_mapper: None,
|
|
||||||
|
|
||||||
print: Box::new(|_| {}),
|
|
||||||
debug: Box::new(|_, _, _| {}),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
progress: None,
|
|
||||||
|
|
||||||
options: LangOptions::new(),
|
|
||||||
|
|
||||||
def_tag: Dynamic::UNIT,
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
|
||||||
optimization_level: OptimizationLevel::Simple,
|
|
||||||
#[cfg(feature = "no_optimize")]
|
|
||||||
optimization_level: (),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
limits: crate::api::limits::Limits::new(),
|
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
|
||||||
debugger_interface: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the global namespace module
|
|
||||||
let mut global_namespace = Module::new();
|
|
||||||
global_namespace.flags |= ModuleFlags::INTERNAL;
|
|
||||||
engine.global_modules.push(global_namespace.into());
|
|
||||||
|
|
||||||
engine
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an interned [string][ImmutableString].
|
/// Get an interned [string][ImmutableString].
|
||||||
@ -338,13 +335,17 @@ impl Engine {
|
|||||||
/// [`Engine`] keeps a cache of [`ImmutableString`] instances and tries to avoid new allocations
|
/// [`Engine`] keeps a cache of [`ImmutableString`] instances and tries to avoid new allocations
|
||||||
/// when an existing instance is found.
|
/// when an existing instance is found.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_interned_string(
|
pub fn get_interned_string(
|
||||||
&self,
|
&self,
|
||||||
string: impl AsRef<str> + Into<ImmutableString>,
|
string: impl AsRef<str> + Into<ImmutableString>,
|
||||||
) -> ImmutableString {
|
) -> ImmutableString {
|
||||||
locked_write(&self.interned_strings).get(string)
|
if let Some(ref interner) = self.interned_strings {
|
||||||
|
locked_write(interner).get(string)
|
||||||
|
} else {
|
||||||
|
string.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an empty [`ImmutableString`] which refers to a shared instance.
|
/// Get an empty [`ImmutableString`] which refers to a shared instance.
|
||||||
|
@ -806,7 +806,7 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
Some(
|
Some(
|
||||||
self.module_resolver
|
self.module_resolver()
|
||||||
.resolve_raw(self, global, scope, &path, path_pos),
|
.resolve_raw(self, global, scope, &path, path_pos),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -459,18 +459,26 @@ impl Engine {
|
|||||||
// See if the function match print/debug (which requires special processing)
|
// See if the function match print/debug (which requires special processing)
|
||||||
return Ok(match name {
|
return Ok(match name {
|
||||||
KEYWORD_PRINT => {
|
KEYWORD_PRINT => {
|
||||||
let text = result.into_immutable_string().map_err(|typ| {
|
if let Some(ref print) = self.print {
|
||||||
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
let text = result.into_immutable_string().map_err(|typ| {
|
||||||
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
||||||
})?;
|
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
||||||
((*self.print)(&text).into(), false)
|
})?;
|
||||||
|
((print)(&text).into(), false)
|
||||||
|
} else {
|
||||||
|
(Dynamic::UNIT, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
KEYWORD_DEBUG => {
|
KEYWORD_DEBUG => {
|
||||||
let text = result.into_immutable_string().map_err(|typ| {
|
if let Some(ref debug) = self.debug {
|
||||||
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
let text = result.into_immutable_string().map_err(|typ| {
|
||||||
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
let t = self.map_type_name(type_name::<ImmutableString>()).into();
|
||||||
})?;
|
ERR::ErrorMismatchOutputType(t, typ.into(), pos)
|
||||||
((*self.debug)(&text, global.source(), pos).into(), false)
|
})?;
|
||||||
|
((debug)(&text, global.source(), pos).into(), false)
|
||||||
|
} else {
|
||||||
|
(Dynamic::UNIT, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => (result, is_method),
|
_ => (result, is_method),
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ use crate::{Dynamic, RhaiResultOf, ERR, INT};
|
|||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
|
|
||||||
def_package! {
|
def_package! {
|
||||||
|
@ -2354,7 +2354,6 @@ impl Engine {
|
|||||||
let op = op_token.to_string();
|
let op = op_token.to_string();
|
||||||
let hash = calc_fn_hash(None, &op, 2);
|
let hash = calc_fn_hash(None, &op, 2);
|
||||||
let native_only = !is_valid_function_name(&op);
|
let native_only = !is_valid_function_name(&op);
|
||||||
let operator_token = native_only.then(|| op_token.clone());
|
|
||||||
|
|
||||||
let mut args = FnArgsVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(root);
|
args.push(root);
|
||||||
@ -2366,7 +2365,7 @@ impl Engine {
|
|||||||
name: state.get_interned_string(&op),
|
name: state.get_interned_string(&op),
|
||||||
hashes: FnCallHashes::from_native_only(hash),
|
hashes: FnCallHashes::from_native_only(hash),
|
||||||
args,
|
args,
|
||||||
op_token: operator_token,
|
op_token: native_only.then(|| op_token.clone()),
|
||||||
capture_parent_scope: false,
|
capture_parent_scope: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user