Refactor to do more pre-calculation work.
This commit is contained in:
parent
9f18d6519d
commit
d0a47d7f66
@ -729,7 +729,7 @@ impl Engine {
|
|||||||
name: &str,
|
name: &str,
|
||||||
module: SharedModule,
|
module: SharedModule,
|
||||||
) {
|
) {
|
||||||
let separator = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
let separator = crate::engine::NAMESPACE_SEPARATOR;
|
||||||
|
|
||||||
if name.contains(separator) {
|
if name.contains(separator) {
|
||||||
let mut iter = name.splitn(2, separator);
|
let mut iter = name.splitn(2, separator);
|
||||||
|
@ -383,7 +383,7 @@ impl fmt::Debug for Expr {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
if !x.1.is_empty() {
|
if !x.1.is_empty() {
|
||||||
write!(f, "{}{}", x.1, Token::DoubleColon.literal_syntax())?;
|
write!(f, "{}{}", x.1, crate::engine::NAMESPACE_SEPARATOR)?;
|
||||||
let pos = x.1.position();
|
let pos = x.1.position();
|
||||||
if !pos.is_none() {
|
if !pos.is_none() {
|
||||||
display_pos = pos;
|
display_pos = pos;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#![cfg(not(feature = "no_module"))]
|
#![cfg(not(feature = "no_module"))]
|
||||||
|
|
||||||
use crate::ast::Ident;
|
use crate::ast::Ident;
|
||||||
use crate::tokenizer::Token;
|
|
||||||
use crate::{Position, StaticVec};
|
use crate::{Position, StaticVec};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -46,7 +45,7 @@ impl fmt::Debug for Namespace {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(Ident::as_str)
|
.map(Ident::as_str)
|
||||||
.collect::<StaticVec<_>>()
|
.collect::<StaticVec<_>>()
|
||||||
.join(Token::DoubleColon.literal_syntax()),
|
.join(crate::engine::NAMESPACE_SEPARATOR),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +62,7 @@ impl fmt::Display for Namespace {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(Ident::as_str)
|
.map(Ident::as_str)
|
||||||
.collect::<StaticVec<_>>()
|
.collect::<StaticVec<_>>()
|
||||||
.join(Token::DoubleColon.literal_syntax()),
|
.join(crate::engine::NAMESPACE_SEPARATOR),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Module defining script statements.
|
//! Module defining script statements.
|
||||||
|
|
||||||
use super::{ASTFlags, ASTNode, BinaryExpr, Expr, FnCallExpr, Ident};
|
use super::{ASTFlags, ASTNode, BinaryExpr, Expr, FnCallExpr, Ident};
|
||||||
use crate::engine::KEYWORD_EVAL;
|
use crate::engine::{KEYWORD_EVAL, OP_EQUALS};
|
||||||
use crate::func::StraightHashMap;
|
use crate::func::StraightHashMap;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::Span;
|
use crate::types::Span;
|
||||||
@ -29,8 +29,12 @@ pub struct OpAssignment {
|
|||||||
hash_op: u64,
|
hash_op: u64,
|
||||||
/// Op-assignment operator.
|
/// Op-assignment operator.
|
||||||
op_assign: Token,
|
op_assign: Token,
|
||||||
|
/// Syntax of op-assignment operator.
|
||||||
|
op_assign_syntax: &'static str,
|
||||||
/// Underlying operator.
|
/// Underlying operator.
|
||||||
op: Token,
|
op: Token,
|
||||||
|
/// Syntax of underlying operator.
|
||||||
|
op_syntax: &'static str,
|
||||||
/// [Position] of the op-assignment operator.
|
/// [Position] of the op-assignment operator.
|
||||||
pos: Position,
|
pos: Position,
|
||||||
}
|
}
|
||||||
@ -44,7 +48,9 @@ impl OpAssignment {
|
|||||||
hash_op_assign: 0,
|
hash_op_assign: 0,
|
||||||
hash_op: 0,
|
hash_op: 0,
|
||||||
op_assign: Token::Equals,
|
op_assign: Token::Equals,
|
||||||
|
op_assign_syntax: OP_EQUALS,
|
||||||
op: Token::Equals,
|
op: Token::Equals,
|
||||||
|
op_syntax: OP_EQUALS,
|
||||||
pos,
|
pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,17 +62,28 @@ impl OpAssignment {
|
|||||||
}
|
}
|
||||||
/// Get information if this [`OpAssignment`] is an op-assignment.
|
/// Get information if this [`OpAssignment`] is an op-assignment.
|
||||||
///
|
///
|
||||||
/// Returns `( hash_op_assign, hash_op, op_assign, op )`:
|
/// Returns `( hash_op_assign, hash_op, op_assign, op_assign_syntax, op, op_syntax )`:
|
||||||
///
|
///
|
||||||
/// * `hash_op_assign`: Hash of the op-assignment call.
|
/// * `hash_op_assign`: Hash of the op-assignment call.
|
||||||
/// * `hash_op`: Hash of the underlying operator call (for fallback).
|
/// * `hash_op`: Hash of the underlying operator call (for fallback).
|
||||||
/// * `op_assign`: Op-assignment operator.
|
/// * `op_assign`: Op-assignment operator.
|
||||||
|
/// * `op_assign_syntax`: Syntax of op-assignment operator.
|
||||||
/// * `op`: Underlying operator.
|
/// * `op`: Underlying operator.
|
||||||
|
/// * `op_syntax`: Syntax of underlying operator.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_op_assignment_info(&self) -> Option<(u64, u64, &Token, &Token)> {
|
pub fn get_op_assignment_info(
|
||||||
|
&self,
|
||||||
|
) -> Option<(u64, u64, &Token, &'static str, &Token, &'static str)> {
|
||||||
if self.is_op_assignment() {
|
if self.is_op_assignment() {
|
||||||
Some((self.hash_op_assign, self.hash_op, &self.op_assign, &self.op))
|
Some((
|
||||||
|
self.hash_op_assign,
|
||||||
|
self.hash_op,
|
||||||
|
&self.op_assign,
|
||||||
|
self.op_assign_syntax,
|
||||||
|
&self.op,
|
||||||
|
self.op_syntax,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -99,11 +116,16 @@ impl OpAssignment {
|
|||||||
.get_base_op_from_assignment()
|
.get_base_op_from_assignment()
|
||||||
.expect("op-assignment operator");
|
.expect("op-assignment operator");
|
||||||
|
|
||||||
|
let op_assign_syntax = op_assign.literal_syntax();
|
||||||
|
let op_syntax = op.literal_syntax();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
hash_op_assign: calc_fn_hash(None, op_assign.literal_syntax(), 2),
|
hash_op_assign: calc_fn_hash(None, op_assign_syntax, 2),
|
||||||
hash_op: calc_fn_hash(None, op.literal_syntax(), 2),
|
hash_op: calc_fn_hash(None, op_syntax, 2),
|
||||||
op_assign,
|
op_assign,
|
||||||
|
op_assign_syntax,
|
||||||
op,
|
op,
|
||||||
|
op_syntax,
|
||||||
pos,
|
pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +161,9 @@ impl fmt::Debug for OpAssignment {
|
|||||||
.field("hash_op_assign", &self.hash_op_assign)
|
.field("hash_op_assign", &self.hash_op_assign)
|
||||||
.field("hash_op", &self.hash_op)
|
.field("hash_op", &self.hash_op)
|
||||||
.field("op_assign", &self.op_assign)
|
.field("op_assign", &self.op_assign)
|
||||||
|
.field("op_assign_syntax", &self.op_assign_syntax)
|
||||||
.field("op", &self.op)
|
.field("op", &self.op)
|
||||||
|
.field("op_syntax", &self.op_syntax)
|
||||||
.field("pos", &self.pos)
|
.field("pos", &self.pos)
|
||||||
.finish()
|
.finish()
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,12 +57,19 @@ pub const OP_EQUALS: &str = Token::EqualsTo.literal_syntax();
|
|||||||
/// The `in` operator is implemented as a call to this function.
|
/// The `in` operator is implemented as a call to this function.
|
||||||
pub const OP_CONTAINS: &str = "contains";
|
pub const OP_CONTAINS: &str = "contains";
|
||||||
|
|
||||||
|
/// Standard not operator.
|
||||||
|
pub const OP_NOT: &str = Token::Bang.literal_syntax();
|
||||||
|
|
||||||
/// Standard exclusive range operator.
|
/// Standard exclusive range operator.
|
||||||
pub const OP_EXCLUSIVE_RANGE: &str = Token::ExclusiveRange.literal_syntax();
|
pub const OP_EXCLUSIVE_RANGE: &str = Token::ExclusiveRange.literal_syntax();
|
||||||
|
|
||||||
/// Standard inclusive range operator.
|
/// Standard inclusive range operator.
|
||||||
pub const OP_INCLUSIVE_RANGE: &str = Token::InclusiveRange.literal_syntax();
|
pub const OP_INCLUSIVE_RANGE: &str = Token::InclusiveRange.literal_syntax();
|
||||||
|
|
||||||
|
/// Separator for namespaces.
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
pub const NAMESPACE_SEPARATOR: &str = Token::DoubleColon.literal_syntax();
|
||||||
|
|
||||||
/// Rhai main scripting engine.
|
/// Rhai main scripting engine.
|
||||||
///
|
///
|
||||||
/// # Thread Safety
|
/// # Thread Safety
|
||||||
|
@ -74,7 +74,7 @@ impl Engine {
|
|||||||
if let Some(module) = self.search_imports(global, ns) {
|
if let Some(module) = self.search_imports(global, ns) {
|
||||||
return module.get_qualified_var(*hash_var).map_or_else(
|
return module.get_qualified_var(*hash_var).map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
let sep = crate::engine::NAMESPACE_SEPARATOR;
|
||||||
|
|
||||||
Err(ERR::ErrorVariableNotFound(
|
Err(ERR::ErrorVariableNotFound(
|
||||||
format!("{ns}{sep}{var_name}"),
|
format!("{ns}{sep}{var_name}"),
|
||||||
@ -104,7 +104,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
|
let sep = crate::engine::NAMESPACE_SEPARATOR;
|
||||||
|
|
||||||
return Err(ERR::ErrorVariableNotFound(
|
return Err(ERR::ErrorVariableNotFound(
|
||||||
format!("{ns}{sep}{var_name}"),
|
format!("{ns}{sep}{var_name}"),
|
||||||
|
@ -127,21 +127,20 @@ impl Engine {
|
|||||||
|
|
||||||
let pos = op_info.position();
|
let pos = op_info.position();
|
||||||
|
|
||||||
if let Some((hash1, hash2, op_assign, op)) = op_info.get_op_assignment_info() {
|
if let Some((hash_x, hash, op_x, op_x_str, op, op_str)) = op_info.get_op_assignment_info() {
|
||||||
let mut lock_guard = target.write_lock::<Dynamic>().unwrap();
|
let mut lock_guard = target.write_lock::<Dynamic>().unwrap();
|
||||||
let args = &mut [&mut *lock_guard, &mut new_val];
|
let args = &mut [&mut *lock_guard, &mut new_val];
|
||||||
|
|
||||||
if self.fast_operators() {
|
if self.fast_operators() {
|
||||||
if let Some((func, need_context)) =
|
if let Some((func, need_context)) =
|
||||||
get_builtin_op_assignment_fn(op_assign, args[0], args[1])
|
get_builtin_op_assignment_fn(op_x, args[0], args[1])
|
||||||
{
|
{
|
||||||
// Built-in found
|
// Built-in found
|
||||||
auto_restore! { let orig_level = global.level; global.level += 1 }
|
auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
|
|
||||||
let context = if need_context {
|
let context = if need_context {
|
||||||
let op = op_assign.literal_syntax();
|
|
||||||
let source = global.source();
|
let source = global.source();
|
||||||
Some((self, op, source, &*global, pos).into())
|
Some((self, op_x_str, source, &*global, pos).into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -149,20 +148,17 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = Some(op_assign);
|
let opx = Some(op_x);
|
||||||
let op_assign = op_assign.literal_syntax();
|
|
||||||
|
|
||||||
match self.exec_native_fn_call(global, caches, op_assign, token, hash1, args, true, pos)
|
match self.exec_native_fn_call(global, caches, op_x_str, opx, hash_x, args, true, pos) {
|
||||||
{
|
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_assign)) =>
|
Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_x_str)) =>
|
||||||
{
|
{
|
||||||
// Expand to `var = var op rhs`
|
// Expand to `var = var op rhs`
|
||||||
let token = Some(op);
|
let op = Some(op);
|
||||||
let op = op.literal_syntax();
|
|
||||||
|
|
||||||
*args[0] = self
|
*args[0] = self
|
||||||
.exec_native_fn_call(global, caches, op, token, hash2, args, true, pos)?
|
.exec_native_fn_call(global, caches, op_str, op, hash, args, true, pos)?
|
||||||
.0;
|
.0;
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
|
@ -1491,7 +1491,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"{namespace}{}{}",
|
"{namespace}{}{}",
|
||||||
crate::tokenizer::Token::DoubleColon.literal_syntax(),
|
crate::engine::NAMESPACE_SEPARATOR,
|
||||||
self.gen_fn_call_signature(fn_name, args)
|
self.gen_fn_call_signature(fn_name, args)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,9 @@ use crate::ast::{
|
|||||||
ASTFlags, Expr, FlowControl, OpAssignment, Stmt, StmtBlock, StmtBlockContainer,
|
ASTFlags, Expr, FlowControl, OpAssignment, Stmt, StmtBlock, StmtBlockContainer,
|
||||||
SwitchCasesCollection,
|
SwitchCasesCollection,
|
||||||
};
|
};
|
||||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
use crate::engine::{
|
||||||
|
KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF, OP_NOT,
|
||||||
|
};
|
||||||
use crate::eval::{Caches, GlobalRuntimeState};
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::func::builtin::get_builtin_binary_op_fn;
|
use crate::func::builtin::get_builtin_binary_op_fn;
|
||||||
use crate::func::hashing::get_hasher;
|
use crate::func::hashing::get_hasher;
|
||||||
@ -25,9 +27,6 @@ use std::{
|
|||||||
mem,
|
mem,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Standard not operator.
|
|
||||||
const OP_NOT: &str = Token::Bang.literal_syntax();
|
|
||||||
|
|
||||||
/// Level of optimization performed.
|
/// Level of optimization performed.
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -287,7 +287,8 @@ fn collect_fn_metadata(
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
use crate::{tokenizer::Token::DoubleColon, Shared, SmartString};
|
use crate::engine::NAMESPACE_SEPARATOR;
|
||||||
|
use crate::{Shared, SmartString};
|
||||||
|
|
||||||
// Recursively scan modules for script-defined functions.
|
// Recursively scan modules for script-defined functions.
|
||||||
fn scan_module(
|
fn scan_module(
|
||||||
@ -305,7 +306,7 @@ fn collect_fn_metadata(
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
let mut ns = SmartString::new_const();
|
let mut ns = SmartString::new_const();
|
||||||
write!(&mut ns, "{namespace}{}{name}", DoubleColon.literal_syntax()).unwrap();
|
write!(&mut ns, "{namespace}{}{name}", NAMESPACE_SEPARATOR).unwrap();
|
||||||
scan_module(engine, list, &ns, m, filter);
|
scan_module(engine, list, &ns, m, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::ast::{
|
|||||||
FnCallHashes, Ident, Namespace, OpAssignment, RangeCase, ScriptFnDef, Stmt, StmtBlock,
|
FnCallHashes, Ident, Namespace, OpAssignment, RangeCase, ScriptFnDef, Stmt, StmtBlock,
|
||||||
StmtBlockContainer, SwitchCasesCollection,
|
StmtBlockContainer, SwitchCasesCollection,
|
||||||
};
|
};
|
||||||
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS};
|
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS, OP_NOT};
|
||||||
use crate::eval::{Caches, GlobalRuntimeState};
|
use crate::eval::{Caches, GlobalRuntimeState};
|
||||||
use crate::func::{hashing::get_hasher, StraightHashMap};
|
use crate::func::{hashing::get_hasher, StraightHashMap};
|
||||||
use crate::tokenizer::{
|
use crate::tokenizer::{
|
||||||
@ -1299,6 +1299,10 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expressions.shrink_to_fit();
|
||||||
|
cases.shrink_to_fit();
|
||||||
|
ranges.shrink_to_fit();
|
||||||
|
|
||||||
let cases = SwitchCasesCollection {
|
let cases = SwitchCasesCollection {
|
||||||
expressions,
|
expressions,
|
||||||
cases,
|
cases,
|
||||||
@ -2418,14 +2422,13 @@ impl Engine {
|
|||||||
fn_call
|
fn_call
|
||||||
} else {
|
} else {
|
||||||
// Put a `!` call in front
|
// Put a `!` call in front
|
||||||
let op = Token::Bang.literal_syntax();
|
|
||||||
let mut args = FnArgsVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(fn_call);
|
args.push(fn_call);
|
||||||
|
|
||||||
let not_base = FnCallExpr {
|
let not_base = FnCallExpr {
|
||||||
namespace: Namespace::NONE,
|
namespace: Namespace::NONE,
|
||||||
name: state.get_interned_string(op),
|
name: state.get_interned_string(OP_NOT),
|
||||||
hashes: FnCallHashes::from_native_only(calc_fn_hash(None, op, 1)),
|
hashes: FnCallHashes::from_native_only(calc_fn_hash(None, OP_NOT, 1)),
|
||||||
args,
|
args,
|
||||||
op_token: Some(Token::Bang),
|
op_token: Some(Token::Bang),
|
||||||
capture_parent_scope: false,
|
capture_parent_scope: false,
|
||||||
|
Loading…
Reference in New Issue
Block a user