Merge pull request #687 from schungx/master

Prepare for release.
This commit is contained in:
Stephen Chung 2022-12-30 22:47:49 +08:00 committed by GitHub
commit 4c2630b71f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 199 additions and 184 deletions

View File

@ -1,7 +1,6 @@
//! Module containing all deprecated API that will be removed in the next major version. //! Module containing all deprecated API that will be removed in the next major version.
use crate::func::RegisterNativeFunction; use crate::func::RegisterNativeFunction;
use crate::plugin::*;
use crate::types::dynamic::Variant; use crate::types::dynamic::Variant;
use crate::{ use crate::{
Dynamic, Engine, EvalAltResult, FnPtr, Identifier, ImmutableString, Module, NativeCallContext, Dynamic, Engine, EvalAltResult, FnPtr, Identifier, ImmutableString, Module, NativeCallContext,
@ -633,6 +632,9 @@ impl Module {
} }
} }
#[cfg(not(feature = "no_index"))]
use crate::plugin::*;
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[export_module] #[export_module]
pub mod deprecated_array_functions { pub mod deprecated_array_functions {

View File

@ -489,11 +489,13 @@ impl Expr {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Self::Map(x, ..) if self.is_constant() => { Self::Map(x, ..) if self.is_constant() => {
Dynamic::from_map(x.0.iter().fold(x.1.clone(), |mut map, (k, v)| { let mut map = x.1.clone();
let value_ref = map.get_mut(k.name.as_str()).unwrap();
*value_ref = v.get_literal_value().unwrap(); for (k, v) in &x.0 {
map *map.get_mut(k.name.as_str()).unwrap() = v.get_literal_value().unwrap();
})) }
Dynamic::from_map(map)
} }
// Interpolated string // Interpolated string

View File

@ -18,23 +18,37 @@ impl Dynamic {
/// Panics if any interior data is shared (should never happen). /// Panics if any interior data is shared (should never happen).
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[inline] #[inline]
pub(crate) fn calc_array_sizes(array: &crate::Array, _top: bool) -> (usize, usize, usize) { pub(crate) fn calc_array_sizes(array: &crate::Array) -> (usize, usize, usize) {
array let (mut ax, mut mx, mut sx) = (0, 0, 0);
.iter()
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 { for value in array {
Union::Array(..) => { ax += 1;
let (a, m, s) = value.calc_data_sizes(false);
(ax + a + 1, mx + m, sx + s) match value.0 {
Union::Array(ref a, ..) => {
let (a, m, s) = Self::calc_array_sizes(a);
ax += a;
mx += m;
sx += s;
} }
Union::Blob(ref a, ..) => (ax + 1 + a.len(), mx, sx), Union::Blob(ref a, ..) => ax += 1 + a.len(),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(..) => { Union::Map(ref m, ..) => {
let (a, m, s) = value.calc_data_sizes(false); let (a, m, s) = Self::calc_map_sizes(m);
(ax + a + 1, mx + m, sx + s) ax += a;
mx += m;
sx += s;
} }
Union::Str(ref s, ..) => (ax + 1, mx, sx + s.len()), Union::Str(ref s, ..) => sx += s.len(),
_ => (ax + 1, mx, sx), #[cfg(not(feature = "no_closure"))]
}) Union::Shared(..) => {
unreachable!("shared values discovered within data")
}
_ => (),
}
}
(ax, mx, sx)
} }
/// Recursively calculate the sizes of a map. /// Recursively calculate the sizes of a map.
/// ///
@ -45,23 +59,38 @@ impl Dynamic {
/// Panics if any interior data is shared (should never happen). /// Panics if any interior data is shared (should never happen).
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline] #[inline]
pub(crate) fn calc_map_sizes(map: &crate::Map, _top: bool) -> (usize, usize, usize) { pub(crate) fn calc_map_sizes(map: &crate::Map) -> (usize, usize, usize) {
map.values() let (mut ax, mut mx, mut sx) = (0, 0, 0);
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
for value in map.values() {
mx += 1;
match value.0 {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(..) => { Union::Array(ref a, ..) => {
let (a, m, s) = value.calc_data_sizes(false); let (a, m, s) = Self::calc_array_sizes(a);
(ax + a, mx + m + 1, sx + s) ax += a;
mx += m;
sx += s;
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Blob(ref a, ..) => (ax + a.len(), mx, sx), Union::Blob(ref a, ..) => ax += 1 + a.len(),
Union::Map(..) => { Union::Map(ref m, ..) => {
let (a, m, s) = value.calc_data_sizes(false); let (a, m, s) = Self::calc_map_sizes(m);
(ax + a, mx + m + 1, sx + s) ax += a;
mx += m;
sx += s;
} }
Union::Str(ref s, ..) => (ax, mx + 1, sx + s.len()), Union::Str(ref s, ..) => sx += s.len(),
_ => (ax, mx + 1, sx), #[cfg(not(feature = "no_closure"))]
}) Union::Shared(..) => {
unreachable!("shared values discovered within data")
}
_ => (),
}
}
(ax, mx, sx)
} }
/// Recursively calculate the sizes of a value. /// Recursively calculate the sizes of a value.
/// ///
@ -74,11 +103,11 @@ impl Dynamic {
pub(crate) fn calc_data_sizes(&self, _top: bool) -> (usize, usize, usize) { pub(crate) fn calc_data_sizes(&self, _top: bool) -> (usize, usize, usize) {
match self.0 { match self.0 {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(ref arr, ..) => Self::calc_array_sizes(&**arr, _top), Union::Array(ref arr, ..) => Self::calc_array_sizes(&**arr),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Blob(ref blob, ..) => (blob.len(), 0, 0), Union::Blob(ref blob, ..) => (blob.len(), 0, 0),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(ref map, ..) => Self::calc_map_sizes(&**map, _top), Union::Map(ref map, ..) => Self::calc_map_sizes(&**map),
Union::Str(ref s, ..) => (0, 0, s.len()), Union::Str(ref s, ..) => (0, 0, s.len()),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(..) if _top => self.read_lock::<Self>().unwrap().calc_data_sizes(true), Union::Shared(..) if _top => self.read_lock::<Self>().unwrap().calc_data_sizes(true),

View File

@ -286,7 +286,7 @@ impl Engine {
Expr::InterpolatedString(x, _) => { Expr::InterpolatedString(x, _) => {
let mut concat = SmartString::new_const(); let mut concat = SmartString::new_const();
x.iter().try_for_each(|expr| -> RhaiResultOf<()> { for expr in &**x {
let item = &mut self let item = &mut self
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.flatten(); .flatten();
@ -304,9 +304,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
self.throw_on_size((0, 0, concat.len())) self.throw_on_size((0, 0, concat.len()))
.map_err(|err| err.fill_position(pos))?; .map_err(|err| err.fill_position(pos))?;
}
Ok(())
})?;
Ok(self.get_interned_string(concat).into()) Ok(self.get_interned_string(concat).into())
} }
@ -318,7 +316,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
let mut total_data_sizes = (0, 0, 0); let mut total_data_sizes = (0, 0, 0);
x.iter().try_for_each(|item_expr| -> RhaiResultOf<()> { for item_expr in &**x {
let value = self let value = self
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), item_expr)? .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), item_expr)?
.flatten(); .flatten();
@ -337,9 +335,7 @@ impl Engine {
} }
array.push(value); array.push(value);
}
Ok(())
})?;
Ok(Dynamic::from_array(array)) Ok(Dynamic::from_array(array))
} }
@ -351,8 +347,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
let mut total_data_sizes = (0, 0, 0); let mut total_data_sizes = (0, 0, 0);
x.0.iter() for (key, value_expr) in &x.0 {
.try_for_each(|(key, value_expr)| -> RhaiResultOf<()> {
let value = self let value = self
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), value_expr)? .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), value_expr)?
.flatten(); .flatten();
@ -370,9 +365,7 @@ impl Engine {
} }
*map.get_mut(key.as_str()).unwrap() = value; *map.get_mut(key.as_str()).unwrap() = value;
}
Ok(())
})?;
Ok(Dynamic::from_map(map)) Ok(Dynamic::from_map(map))
} }

View File

@ -129,9 +129,9 @@ impl Engine {
let OpAssignment { let OpAssignment {
hash_op_assign, hash_op_assign,
hash_op, hash_op,
op_assign: op_assign_token, op_assign,
op: op_token, op,
pos: op_pos, pos,
} = op_info; } = op_info;
let mut lock_guard = target.write_lock::<Dynamic>().unwrap(); let mut lock_guard = target.write_lock::<Dynamic>().unwrap();
@ -141,15 +141,15 @@ impl Engine {
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_token.clone(), args[0], args[1]) get_builtin_op_assignment_fn(op_assign.clone(), args[0], args[1])
{ {
// Built-in found // Built-in found
let op = op_assign_token.literal_syntax();
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, *op_pos).into()) Some((self, op, source, &*global, *pos).into())
} else { } else {
None None
}; };
@ -157,23 +157,20 @@ impl Engine {
} }
} }
let op_assign = op_assign_token.literal_syntax(); let token = Some(op_assign.clone());
let op = op_token.literal_syntax(); let op_assign = op_assign.literal_syntax();
let token = Some(op_assign_token.clone());
match self match self.exec_native_fn_call(global, caches, op_assign, token, hash, args, true, *pos)
.exec_native_fn_call(global, caches, op_assign, token, hash, args, true, *op_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_assign)) =>
{ {
// Expand to `var = var op rhs` // Expand to `var = var op rhs`
let token = Some(op_token.clone()); let token = Some(op.clone());
let op = op.literal_syntax();
*args[0] = self *args[0] = self
.exec_native_fn_call( .exec_native_fn_call(global, caches, op, token, *hash_op, args, true, *pos)?
global, caches, op, token, *hash_op, args, true, *op_pos,
)?
.0; .0;
} }
Err(err) => return Err(err), Err(err) => return Err(err),
@ -864,25 +861,23 @@ impl Engine {
// Share statement // Share statement
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(x) => { Stmt::Share(x) => {
x.iter() for (name, index, pos) in &**x {
.try_for_each(|(name, index, pos)| { if let Some(index) = index
index
.map(|n| scope.len() - n.get()) .map(|n| scope.len() - n.get())
.or_else(|| scope.search(name)) .or_else(|| scope.search(name))
.map_or_else( {
|| Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()),
|index| {
let val = scope.get_mut_by_index(index); let val = scope.get_mut_by_index(index);
if !val.is_shared() { if !val.is_shared() {
// Replace the variable with a shared value. // Replace the variable with a shared value.
*val = std::mem::take(val).into_shared(); *val = std::mem::take(val).into_shared();
} }
Ok(()) } else {
}, return Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into());
) }
}) }
.map(|_| Dynamic::UNIT)
Ok(Dynamic::UNIT)
} }
_ => unreachable!("statement cannot be evaluated: {:?}", stmt), _ => unreachable!("statement cannot be evaluated: {:?}", stmt),

View File

@ -1118,12 +1118,11 @@ impl Engine {
let mut fn_ptr = arg_value.cast::<FnPtr>(); let mut fn_ptr = arg_value.cast::<FnPtr>();
// Append the new curried arguments to the existing list. // Append the new curried arguments to the existing list.
a_expr.iter().try_for_each(|expr| -> Result<_, RhaiError> { for expr in a_expr {
let (value, ..) = let (value, ..) =
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?; self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
fn_ptr.add_curry(value); fn_ptr.add_curry(value);
Ok(()) }
})?;
return Ok(fn_ptr.into()); return Ok(fn_ptr.into());
} }
@ -1229,14 +1228,11 @@ impl Engine {
// If so, do it separately because we cannot convert the first argument (if it is a simple // If so, do it separately because we cannot convert the first argument (if it is a simple
// variable access) to &mut because `scope` is needed. // variable access) to &mut because `scope` is needed.
if capture_scope && !scope.is_empty() { if capture_scope && !scope.is_empty() {
first_arg for expr in first_arg.iter().copied().chain(a_expr.iter()) {
.iter() let (value, ..) =
.copied() self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
.chain(a_expr.iter()) arg_values.push(value.flatten());
.try_for_each(|expr| { }
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
args.extend(curry.iter_mut()); args.extend(curry.iter_mut());
args.extend(arg_values.iter_mut()); args.extend(arg_values.iter_mut());
@ -1265,10 +1261,11 @@ impl Engine {
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?; self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
// func(x, ...) -> x.func(...) // func(x, ...) -> x.func(...)
a_expr.iter().try_for_each(|expr| { for expr in a_expr {
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) let (value, ..) =
.map(|(value, ..)| arg_values.push(value.flatten())) self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
})?; arg_values.push(value.flatten());
}
let mut target = let mut target =
self.search_namespace(global, caches, scope, this_ptr, first_expr)?; self.search_namespace(global, caches, scope, this_ptr, first_expr)?;
@ -1289,13 +1286,11 @@ impl Engine {
} }
} else { } else {
// func(..., ...) // func(..., ...)
first_arg for expr in first_arg.into_iter().chain(a_expr.iter()) {
.into_iter() let (value, ..) =
.chain(a_expr.iter()) self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
.try_for_each(|expr| { arg_values.push(value.flatten());
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) }
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
args.extend(curry.iter_mut()); args.extend(curry.iter_mut());
} }
@ -1345,10 +1340,11 @@ impl Engine {
// func(x, ...) -> x.func(...) // func(x, ...) -> x.func(...)
arg_values.push(Dynamic::UNIT); arg_values.push(Dynamic::UNIT);
args_expr.iter().skip(1).try_for_each(|expr| { for expr in args_expr.iter().skip(1) {
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) let (value, ..) =
.map(|(value, ..)| arg_values.push(value.flatten())) self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
})?; arg_values.push(value.flatten());
}
// Get target reference to first argument // Get target reference to first argument
let first_arg = &args_expr[0]; let first_arg = &args_expr[0];
@ -1374,10 +1370,11 @@ impl Engine {
} }
} else { } else {
// func(..., ...) or func(mod::x, ...) // func(..., ...) or func(mod::x, ...)
args_expr.iter().try_for_each(|expr| { for expr in args_expr {
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) let (value, ..) =
.map(|(value, ..)| arg_values.push(value.flatten())) self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
})?; arg_values.push(value.flatten());
}
args.extend(arg_values.iter_mut()); args.extend(arg_values.iter_mut());
} }
} }

View File

@ -237,7 +237,7 @@ pub mod array_functions {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _ctx.engine().max_array_size() > 0 { if _ctx.engine().max_array_size() > 0 {
let pad = len - array.len(); let pad = len - array.len();
let (a, m, s) = Dynamic::calc_array_sizes(array, true); let (a, m, s) = Dynamic::calc_array_sizes(array);
let (ax, mx, sx) = item.calc_data_sizes(true); let (ax, mx, sx) = item.calc_data_sizes(true);
_ctx.engine() _ctx.engine()

View File

@ -546,11 +546,11 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
settings: ParseSettings,
id: ImmutableString, id: ImmutableString,
no_args: bool, no_args: bool,
capture_parent_scope: bool, capture_parent_scope: bool,
namespace: Namespace, namespace: Namespace,
settings: ParseSettings,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
let (token, token_pos) = if no_args { let (token, token_pos) = if no_args {
&(Token::RightParen, Position::NONE) &(Token::RightParen, Position::NONE)
@ -743,10 +743,10 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
settings: ParseSettings,
lhs: Expr, lhs: Expr,
options: ASTFlags, options: ASTFlags,
check_index_type: bool, check_index_type: bool,
settings: ParseSettings,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
let mut settings = settings; let mut settings = settings;
@ -869,7 +869,7 @@ impl Engine {
_ => unreachable!("`[` or `?[`"), _ => unreachable!("`[` or `?[`"),
}; };
let idx_expr = self.parse_index_chain( let idx_expr = self.parse_index_chain(
input, state, lib, idx_expr, options, false, settings, input, state, lib, settings, idx_expr, options, false,
)?; )?;
// Indexing binds to right // Indexing binds to right
Ok(Expr::Index( Ok(Expr::Index(
@ -1307,8 +1307,8 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
is_property: bool,
settings: ParseSettings, settings: ParseSettings,
is_property: bool,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
let (token, token_pos) = input.peek().expect(NEVER_ENDS); let (token, token_pos) = input.peek().expect(NEVER_ENDS);
@ -1460,7 +1460,7 @@ impl Engine {
}; };
let result = let result =
self.parse_anon_fn(input, new_state, state, lib, new_settings.level_up()?); self.parse_anon_fn(input, new_state, lib, new_settings.level_up()?, state);
// Restore the strings interner by swapping it back // Restore the strings interner by swapping it back
std::mem::swap(state.interned_strings, new_state.interned_strings); std::mem::swap(state.interned_strings, new_state.interned_strings);
@ -1468,12 +1468,8 @@ impl Engine {
let (expr, fn_def) = result?; let (expr, fn_def) = result?;
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
new_state for Ident { name, pos } in new_state.external_vars.as_deref().into_iter().flatten()
.external_vars {
.as_deref()
.into_iter()
.flatten()
.try_for_each(|Ident { name, pos }| {
let (index, is_func) = state.access_var(name, lib, *pos); let (index, is_func) = state.access_var(name, lib, *pos);
if !is_func if !is_func
@ -1485,11 +1481,9 @@ impl Engine {
// If the parent scope is not inside another capturing closure // If the parent scope is not inside another capturing closure
// then we can conclude that the captured variable doesn't exist. // then we can conclude that the captured variable doesn't exist.
// Under Strict Variables mode, this is not allowed. // Under Strict Variables mode, this is not allowed.
Err(PERR::VariableUndefined(name.to_string()).into_err(*pos)) return Err(PERR::VariableUndefined(name.to_string()).into_err(*pos));
} else { }
Ok(())
} }
})?;
let hash_script = calc_fn_hash(None, &fn_def.name, fn_def.params.len()); let hash_script = calc_fn_hash(None, &fn_def.name, fn_def.params.len());
lib.insert(hash_script, fn_def); lib.insert(hash_script, fn_def);
@ -1696,7 +1690,7 @@ impl Engine {
return Ok(root_expr); return Ok(root_expr);
} }
self.parse_postfix(input, state, lib, root_expr, settings) self.parse_postfix(input, state, lib, settings, root_expr)
} }
/// Tail processing of all possible postfix operators of a primary expression. /// Tail processing of all possible postfix operators of a primary expression.
@ -1705,8 +1699,8 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
mut lhs: Expr,
settings: ParseSettings, settings: ParseSettings,
mut lhs: Expr,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
let mut settings = settings; let mut settings = settings;
@ -1753,14 +1747,14 @@ impl Engine {
let (.., ns, _, name) = *x; let (.., ns, _, name) = *x;
settings.pos = pos; settings.pos = pos;
self.parse_fn_call(input, state, lib, name, no_args, true, ns, settings)? self.parse_fn_call(input, state, lib, settings, name, no_args, true, ns)?
} }
// Function call // Function call
(Expr::Variable(x, .., pos), t @ (Token::LeftParen | Token::Unit)) => { (Expr::Variable(x, .., pos), t @ (Token::LeftParen | Token::Unit)) => {
let (.., ns, _, name) = *x; let (.., ns, _, name) = *x;
let no_args = t == Token::Unit; let no_args = t == Token::Unit;
settings.pos = pos; settings.pos = pos;
self.parse_fn_call(input, state, lib, name, no_args, false, ns, settings)? self.parse_fn_call(input, state, lib, settings, name, no_args, false, ns)?
} }
// module access // module access
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -1786,7 +1780,7 @@ impl Engine {
_ => unreachable!("`[` or `?[`"), _ => unreachable!("`[` or `?[`"),
}; };
let settings = settings.level_up()?; let settings = settings.level_up()?;
self.parse_index_chain(input, state, lib, expr, opt, true, settings)? self.parse_index_chain(input, state, lib, settings, expr, opt, true)?
} }
// Property access // Property access
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
@ -1807,7 +1801,7 @@ impl Engine {
(.., pos) => return Err(PERR::PropertyExpected.into_err(*pos)), (.., pos) => return Err(PERR::PropertyExpected.into_err(*pos)),
} }
let rhs = self.parse_primary(input, state, lib, true, settings.level_up()?)?; let rhs = self.parse_primary(input, state, lib, settings.level_up()?, true)?;
let op_flags = match op { let op_flags = match op {
Token::Period => ASTFlags::NONE, Token::Period => ASTFlags::NONE,
Token::Elvis => ASTFlags::NEGATED, Token::Elvis => ASTFlags::NEGATED,
@ -1984,7 +1978,7 @@ impl Engine {
// <EOF> // <EOF>
Token::EOF => Err(PERR::UnexpectedEOF.into_err(settings.pos)), Token::EOF => Err(PERR::UnexpectedEOF.into_err(settings.pos)),
// All other tokens // All other tokens
_ => self.parse_primary(input, state, lib, false, settings), _ => self.parse_primary(input, state, lib, settings, false),
} }
} }
@ -2234,9 +2228,9 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
settings: ParseSettings,
parent_precedence: Option<Precedence>, parent_precedence: Option<Precedence>,
lhs: Expr, lhs: Expr,
settings: ParseSettings,
) -> ParseResult<Expr> { ) -> ParseResult<Expr> {
let mut settings = settings; let mut settings = settings;
settings.pos = lhs.position(); settings.pos = lhs.position();
@ -2294,7 +2288,7 @@ impl Engine {
// If same precedence, then check if the operator binds right // If same precedence, then check if the operator binds right
let rhs = let rhs =
if (precedence == next_precedence && bind_right) || precedence < next_precedence { if (precedence == next_precedence && bind_right) || precedence < next_precedence {
self.parse_binary_op(input, state, lib, precedence, rhs, settings)? self.parse_binary_op(input, state, lib, settings, precedence, rhs)?
} else { } else {
// Otherwise bind to left (even if next operator has the same precedence) // Otherwise bind to left (even if next operator has the same precedence)
rhs rhs
@ -2629,7 +2623,7 @@ impl Engine {
let precedence = Precedence::new(1); let precedence = Precedence::new(1);
let settings = settings.level_up()?; let settings = settings.level_up()?;
let lhs = self.parse_unary(input, state, lib, settings)?; let lhs = self.parse_unary(input, state, lib, settings)?;
self.parse_binary_op(input, state, lib, precedence, lhs, settings) self.parse_binary_op(input, state, lib, settings, precedence, lhs)
} }
/// Parse an if statement. /// Parse an if statement.
@ -2863,9 +2857,9 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
settings: ParseSettings,
access: AccessMode, access: AccessMode,
is_export: bool, is_export: bool,
settings: ParseSettings,
) -> ParseResult<Stmt> { ) -> ParseResult<Stmt> {
// let/const... (specified in `var_type`) // let/const... (specified in `var_type`)
let mut settings = settings; let mut settings = settings;
@ -3016,7 +3010,7 @@ impl Engine {
let pos = *pos; let pos = *pos;
let settings = settings.level_up()?; let settings = settings.level_up()?;
let mut stmt = let mut stmt =
self.parse_let(input, state, lib, AccessMode::ReadWrite, true, settings)?; self.parse_let(input, state, lib, settings, AccessMode::ReadWrite, true)?;
stmt.set_position(pos); stmt.set_position(pos);
return Ok(stmt); return Ok(stmt);
} }
@ -3024,7 +3018,7 @@ impl Engine {
let pos = *pos; let pos = *pos;
let settings = settings.level_up()?; let settings = settings.level_up()?;
let mut stmt = let mut stmt =
self.parse_let(input, state, lib, AccessMode::ReadOnly, true, settings)?; self.parse_let(input, state, lib, settings, AccessMode::ReadOnly, true)?;
stmt.set_position(pos); stmt.set_position(pos);
return Ok(stmt); return Ok(stmt);
} }
@ -3344,8 +3338,8 @@ impl Engine {
input, input,
new_state, new_state,
lib, lib,
access,
new_settings, new_settings,
access,
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
comments, comments,
)?; )?;
@ -3455,9 +3449,9 @@ impl Engine {
Token::Try => self.parse_try_catch(input, state, lib, settings.level_up()?), Token::Try => self.parse_try_catch(input, state, lib, settings.level_up()?),
Token::Let => self.parse_let(input, state, lib, ReadWrite, false, settings.level_up()?), Token::Let => self.parse_let(input, state, lib, settings.level_up()?, ReadWrite, false),
Token::Const => { Token::Const => {
self.parse_let(input, state, lib, ReadOnly, false, settings.level_up()?) self.parse_let(input, state, lib, settings.level_up()?, ReadOnly, false)
} }
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -3555,8 +3549,8 @@ impl Engine {
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
access: crate::FnAccess,
settings: ParseSettings, settings: ParseSettings,
access: crate::FnAccess,
#[cfg(feature = "metadata")] comments: impl IntoIterator<Item = Identifier>, #[cfg(feature = "metadata")] comments: impl IntoIterator<Item = Identifier>,
) -> ParseResult<ScriptFnDef> { ) -> ParseResult<ScriptFnDef> {
let settings = settings.level_up()?; let settings = settings.level_up()?;
@ -3712,9 +3706,9 @@ impl Engine {
&self, &self,
input: &mut TokenStream, input: &mut TokenStream,
state: &mut ParseState, state: &mut ParseState,
_parent: &mut ParseState,
lib: &mut FnLib, lib: &mut FnLib,
settings: ParseSettings, settings: ParseSettings,
_parent: &mut ParseState,
) -> ParseResult<(Expr, Shared<ScriptFnDef>)> { ) -> ParseResult<(Expr, Shared<ScriptFnDef>)> {
let settings = settings.level_up()?; let settings = settings.level_up()?;
let mut params_list = StaticVec::<ImmutableString>::new_const(); let mut params_list = StaticVec::<ImmutableString>::new_const();

View File

@ -371,6 +371,7 @@ impl FnPtr {
/// of arguments to call it directly (one version attaches extra arguments). /// of arguments to call it directly (one version attaches extra arguments).
#[cfg(not(feature = "internals"))] #[cfg(not(feature = "internals"))]
#[inline(always)] #[inline(always)]
#[allow(dead_code)]
pub(crate) fn call_raw_with_extra_args<const N: usize, const E: usize>( pub(crate) fn call_raw_with_extra_args<const N: usize, const E: usize>(
&self, &self,
fn_name: &str, fn_name: &str,

View File

@ -112,20 +112,22 @@ impl StringsInterner {
// We leave at least two entries, one for the empty string, and one for the string // We leave at least two entries, one for the empty string, and one for the string
// that has just been inserted. // that has just been inserted.
while self.cache.len() > MAX_INTERNED_STRINGS - 3 { while self.cache.len() > MAX_INTERNED_STRINGS - 3 {
let (_, _, n) = self let mut max_len = 0;
.cache let mut min_count = usize::MAX;
.iter() let mut index = 0;
.fold((0, usize::MAX, 0), |(x, c, n), (&k, v)| {
if k != skip_hash
&& (v.strong_count() < c || (v.strong_count() == c && v.len() > x))
{
(v.len(), v.strong_count(), k)
} else {
(x, c, n)
}
});
self.cache.remove(&n); for (&k, v) in &self.cache {
if k != skip_hash
&& (v.strong_count() < min_count
|| (v.strong_count() == min_count && v.len() > max_len))
{
max_len = v.len();
min_count = v.strong_count();
index = k;
}
}
self.cache.remove(&index);
} }
} }