diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 11a39eb2..957a195e 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -5,8 +5,8 @@ use crate::engine::{KEYWORD_FN_PTR, OP_EXCLUSIVE_RANGE, OP_INCLUSIVE_RANGE}; use crate::tokenizer::Token; use crate::types::dynamic::Union; use crate::{ - calc_fn_hash, Dynamic, FnPtr, Identifier, ImmutableString, Position, SmartString, StaticVec, - INT, + calc_fn_hash, Dynamic, FnArgsVec, FnPtr, Identifier, ImmutableString, Position, SmartString, + StaticVec, INT, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -201,7 +201,7 @@ pub struct FnCallExpr { /// Pre-calculated hashes. pub hashes: FnCallHashes, /// List of function call argument expressions. - pub args: StaticVec, + pub args: FnArgsVec, /// Does this function call capture the parent scope? pub capture_parent_scope: bool, /// Is this function call a native operator? diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 00ed80e2..139475cf 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -24,15 +24,15 @@ use std::{ #[derive(Clone, PartialEq, Hash)] pub struct OpAssignment { /// Hash of the op-assignment call. - pub hash_op_assign: u64, + hash_op_assign: u64, /// Hash of the underlying operator call (for fallback). - pub hash_op: u64, + hash_op: u64, /// Op-assignment operator. - pub op_assign: Token, + op_assign: Token, /// Underlying operator. - pub op: Token, + op: Token, /// [Position] of the op-assignment operator. - pub pos: Position, + pos: Position, } impl OpAssignment { @@ -51,8 +51,31 @@ impl OpAssignment { /// Is this an op-assignment? #[must_use] #[inline(always)] - pub const fn is_op_assignment(&self) -> bool { - self.hash_op_assign != 0 || self.hash_op != 0 + pub fn is_op_assignment(&self) -> bool { + !matches!(self.op, Token::Equals) + } + /// Get information if this [`OpAssignment`] is an op-assignment. + /// + /// Returns `( hash_op_assign, hash_op, op_assign, op )`: + /// + /// * `hash_op_assign`: Hash of the op-assignment call. + /// * `hash_op`: Hash of the underlying operator call (for fallback). + /// * `op_assign`: Op-assignment operator. + /// * `op`: Underlying operator. + #[must_use] + #[inline] + pub fn get_op_assignment_info(&self) -> Option<(u64, u64, &Token, &Token)> { + if self.is_op_assignment() { + Some((self.hash_op_assign, self.hash_op, &self.op_assign, &self.op)) + } else { + None + } + } + /// Get the [position][Position] of this [`OpAssignment`]. + #[must_use] + #[inline(always)] + pub const fn position(&self) -> Position { + self.pos } /// Create a new [`OpAssignment`]. /// diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index 6833e923..09066c8c 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -621,7 +621,7 @@ impl Engine { self.eval_op_assignment( global, caches, op_info, root, obj_ptr, new_val, )?; - self.check_data_size(obj_ptr.as_ref(), op_info.pos)?; + self.check_data_size(obj_ptr.as_ref(), op_info.position())?; None } // Indexed value cannot be referenced - use indexer @@ -647,7 +647,7 @@ impl Engine { )?; // Replace new value new_val = val.take_or_clone(); - self.check_data_size(&new_val, op_info.pos)?; + self.check_data_size(&new_val, op_info.position())?; } } @@ -729,7 +729,7 @@ impl Engine { global, caches, op_info, root, val_target, new_val, )?; } - self.check_data_size(target.source(), op_info.pos)?; + self.check_data_size(target.source(), op_info.position())?; Ok((Dynamic::UNIT, true)) } // {xxx:map}.id diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index ebd78364..417049b8 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -125,18 +125,10 @@ impl Engine { return Err(ERR::ErrorAssignmentToConstant(name.to_string(), pos).into()); } - if op_info.is_op_assignment() { - let OpAssignment { - hash_op_assign, - hash_op, - op_assign, - op, - pos, - } = op_info; + let pos = op_info.position(); + if let Some((hash1, hash2, op_assign, op)) = op_info.get_op_assignment_info() { let mut lock_guard = target.write_lock::().unwrap(); - - let hash = *hash_op_assign; let args = &mut [&mut *lock_guard, &mut new_val]; if self.fast_operators() { @@ -149,7 +141,7 @@ impl Engine { let context = if need_context { let op = op_assign.literal_syntax(); let source = global.source(); - Some((self, op, source, &*global, *pos).into()) + Some((self, op, source, &*global, pos).into()) } else { None }; @@ -160,7 +152,7 @@ impl Engine { let token = Some(op_assign); let op_assign = op_assign.literal_syntax(); - match self.exec_native_fn_call(global, caches, op_assign, token, hash, args, true, *pos) + match self.exec_native_fn_call(global, caches, op_assign, token, hash1, args, true, pos) { Ok(_) => (), Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_assign)) => @@ -170,7 +162,7 @@ impl Engine { let op = op.literal_syntax(); *args[0] = self - .exec_native_fn_call(global, caches, op, token, *hash_op, args, true, *pos)? + .exec_native_fn_call(global, caches, op, token, hash2, args, true, pos)? .0; } Err(err) => return Err(err), @@ -189,7 +181,7 @@ impl Engine { } } - target.propagate_changed_value(op_info.pos) + target.propagate_changed_value(pos) } /// Evaluate a statement. diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index 80449e92..a5af5296 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -513,7 +513,11 @@ pub mod blob_functions { /// /// print(b); // prints "[030405]" /// ``` - #[allow(clippy::cast_sign_loss, clippy::needless_pass_by_value, clippy::cast_possible_truncation)] + #[allow( + clippy::cast_sign_loss, + clippy::needless_pass_by_value, + clippy::cast_possible_truncation + )] pub fn chop(blob: &mut Blob, len: INT) { if !blob.is_empty() { if len <= 0 { diff --git a/src/parser.rs b/src/parser.rs index 46c37a27..9f8c6e1f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -17,9 +17,9 @@ use crate::tokenizer::{ use crate::types::dynamic::AccessMode; use crate::types::StringsInterner; use crate::{ - calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ExclusiveRange, Identifier, - ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, Scope, - Shared, SmartString, StaticVec, AST, INT, PERR, + calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ExclusiveRange, FnArgsVec, + Identifier, ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, + Scope, Shared, SmartString, StaticVec, AST, INT, PERR, }; use bitflags::bitflags; #[cfg(feature = "no_std")] @@ -567,7 +567,7 @@ impl Engine { }; let mut _namespace = namespace; - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); match token { // id( @@ -1945,7 +1945,7 @@ impl Engine { // Call negative function expr => { - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); args.push(expr); args.shrink_to_fit(); @@ -1973,7 +1973,7 @@ impl Engine { // Call plus function expr => { - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); args.push(expr); args.shrink_to_fit(); @@ -1994,7 +1994,7 @@ impl Engine { let token = token.clone(); let pos = eat_token(input, Token::Bang); - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); args.push(self.parse_unary(input, state, lib, settings.level_up()?)?); args.shrink_to_fit(); @@ -2359,7 +2359,7 @@ impl Engine { Some(op_token.clone()) }; - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); args.push(root); args.push(rhs); args.shrink_to_fit(); @@ -2419,7 +2419,7 @@ impl Engine { } else { // Put a `!` call in front let op = Token::Bang.literal_syntax(); - let mut args = StaticVec::new_const(); + let mut args = FnArgsVec::new_const(); args.push(fn_call); let not_base = FnCallExpr { @@ -3708,7 +3708,7 @@ impl Engine { } let num_externals = externals.len(); - let mut args = StaticVec::with_capacity(externals.len() + 1); + let mut args = FnArgsVec::with_capacity(externals.len() + 1); args.push(fn_expr);