Fix op-assignment hashes.
This commit is contained in:
parent
9cb5154979
commit
557b368fdb
@ -5,8 +5,8 @@ use crate::engine::{KEYWORD_FN_PTR, OP_EXCLUSIVE_RANGE, OP_INCLUSIVE_RANGE};
|
|||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::dynamic::Union;
|
use crate::types::dynamic::Union;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, Dynamic, FnPtr, Identifier, ImmutableString, Position, SmartString, StaticVec,
|
calc_fn_hash, Dynamic, FnArgsVec, FnPtr, Identifier, ImmutableString, Position, SmartString,
|
||||||
INT,
|
StaticVec, INT,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -201,7 +201,7 @@ pub struct FnCallExpr {
|
|||||||
/// Pre-calculated hashes.
|
/// Pre-calculated hashes.
|
||||||
pub hashes: FnCallHashes,
|
pub hashes: FnCallHashes,
|
||||||
/// List of function call argument expressions.
|
/// List of function call argument expressions.
|
||||||
pub args: StaticVec<Expr>,
|
pub args: FnArgsVec<Expr>,
|
||||||
/// Does this function call capture the parent scope?
|
/// Does this function call capture the parent scope?
|
||||||
pub capture_parent_scope: bool,
|
pub capture_parent_scope: bool,
|
||||||
/// Is this function call a native operator?
|
/// Is this function call a native operator?
|
||||||
|
@ -24,15 +24,15 @@ use std::{
|
|||||||
#[derive(Clone, PartialEq, Hash)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct OpAssignment {
|
pub struct OpAssignment {
|
||||||
/// Hash of the op-assignment call.
|
/// Hash of the op-assignment call.
|
||||||
pub hash_op_assign: u64,
|
hash_op_assign: u64,
|
||||||
/// Hash of the underlying operator call (for fallback).
|
/// Hash of the underlying operator call (for fallback).
|
||||||
pub hash_op: u64,
|
hash_op: u64,
|
||||||
/// Op-assignment operator.
|
/// Op-assignment operator.
|
||||||
pub op_assign: Token,
|
op_assign: Token,
|
||||||
/// Underlying operator.
|
/// Underlying operator.
|
||||||
pub op: Token,
|
op: Token,
|
||||||
/// [Position] of the op-assignment operator.
|
/// [Position] of the op-assignment operator.
|
||||||
pub pos: Position,
|
pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpAssignment {
|
impl OpAssignment {
|
||||||
@ -51,8 +51,31 @@ impl OpAssignment {
|
|||||||
/// Is this an op-assignment?
|
/// Is this an op-assignment?
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn is_op_assignment(&self) -> bool {
|
pub fn is_op_assignment(&self) -> bool {
|
||||||
self.hash_op_assign != 0 || self.hash_op != 0
|
!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`].
|
/// Create a new [`OpAssignment`].
|
||||||
///
|
///
|
||||||
|
@ -621,7 +621,7 @@ impl Engine {
|
|||||||
self.eval_op_assignment(
|
self.eval_op_assignment(
|
||||||
global, caches, op_info, root, obj_ptr, new_val,
|
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
|
None
|
||||||
}
|
}
|
||||||
// Indexed value cannot be referenced - use indexer
|
// Indexed value cannot be referenced - use indexer
|
||||||
@ -647,7 +647,7 @@ impl Engine {
|
|||||||
)?;
|
)?;
|
||||||
// Replace new value
|
// Replace new value
|
||||||
new_val = val.take_or_clone();
|
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,
|
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))
|
Ok((Dynamic::UNIT, true))
|
||||||
}
|
}
|
||||||
// {xxx:map}.id
|
// {xxx:map}.id
|
||||||
|
@ -125,18 +125,10 @@ impl Engine {
|
|||||||
return Err(ERR::ErrorAssignmentToConstant(name.to_string(), pos).into());
|
return Err(ERR::ErrorAssignmentToConstant(name.to_string(), pos).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if op_info.is_op_assignment() {
|
let pos = op_info.position();
|
||||||
let OpAssignment {
|
|
||||||
hash_op_assign,
|
|
||||||
hash_op,
|
|
||||||
op_assign,
|
|
||||||
op,
|
|
||||||
pos,
|
|
||||||
} = op_info;
|
|
||||||
|
|
||||||
|
if let Some((hash1, hash2, op_assign, op)) = 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 hash = *hash_op_assign;
|
|
||||||
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() {
|
||||||
@ -149,7 +141,7 @@ impl Engine {
|
|||||||
let context = if need_context {
|
let context = if need_context {
|
||||||
let op = op_assign.literal_syntax();
|
let op = op_assign.literal_syntax();
|
||||||
let source = global.source();
|
let source = global.source();
|
||||||
Some((self, op, source, &*global, *pos).into())
|
Some((self, op, source, &*global, pos).into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -160,7 +152,7 @@ impl Engine {
|
|||||||
let token = Some(op_assign);
|
let token = Some(op_assign);
|
||||||
let op_assign = op_assign.literal_syntax();
|
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(_) => (),
|
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)) =>
|
||||||
@ -170,7 +162,7 @@ impl Engine {
|
|||||||
let op = op.literal_syntax();
|
let op = op.literal_syntax();
|
||||||
|
|
||||||
*args[0] = self
|
*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;
|
.0;
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
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.
|
/// Evaluate a statement.
|
||||||
|
@ -513,7 +513,11 @@ pub mod blob_functions {
|
|||||||
///
|
///
|
||||||
/// print(b); // prints "[030405]"
|
/// 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) {
|
pub fn chop(blob: &mut Blob, len: INT) {
|
||||||
if !blob.is_empty() {
|
if !blob.is_empty() {
|
||||||
if len <= 0 {
|
if len <= 0 {
|
||||||
|
@ -17,9 +17,9 @@ use crate::tokenizer::{
|
|||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::types::StringsInterner;
|
use crate::types::StringsInterner;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ExclusiveRange, Identifier,
|
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ExclusiveRange, FnArgsVec,
|
||||||
ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position, Scope,
|
Identifier, ImmutableString, InclusiveRange, LexError, OptimizationLevel, ParseError, Position,
|
||||||
Shared, SmartString, StaticVec, AST, INT, PERR,
|
Scope, Shared, SmartString, StaticVec, AST, INT, PERR,
|
||||||
};
|
};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
@ -567,7 +567,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut _namespace = namespace;
|
let mut _namespace = namespace;
|
||||||
let mut args = StaticVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
// id( <EOF>
|
// id( <EOF>
|
||||||
@ -1945,7 +1945,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Call negative function
|
// Call negative function
|
||||||
expr => {
|
expr => {
|
||||||
let mut args = StaticVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(expr);
|
args.push(expr);
|
||||||
args.shrink_to_fit();
|
args.shrink_to_fit();
|
||||||
|
|
||||||
@ -1973,7 +1973,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Call plus function
|
// Call plus function
|
||||||
expr => {
|
expr => {
|
||||||
let mut args = StaticVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(expr);
|
args.push(expr);
|
||||||
args.shrink_to_fit();
|
args.shrink_to_fit();
|
||||||
|
|
||||||
@ -1994,7 +1994,7 @@ impl Engine {
|
|||||||
let token = token.clone();
|
let token = token.clone();
|
||||||
let pos = eat_token(input, Token::Bang);
|
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.push(self.parse_unary(input, state, lib, settings.level_up()?)?);
|
||||||
args.shrink_to_fit();
|
args.shrink_to_fit();
|
||||||
|
|
||||||
@ -2359,7 +2359,7 @@ impl Engine {
|
|||||||
Some(op_token.clone())
|
Some(op_token.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut args = StaticVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(root);
|
args.push(root);
|
||||||
args.push(rhs);
|
args.push(rhs);
|
||||||
args.shrink_to_fit();
|
args.shrink_to_fit();
|
||||||
@ -2419,7 +2419,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
// Put a `!` call in front
|
// Put a `!` call in front
|
||||||
let op = Token::Bang.literal_syntax();
|
let op = Token::Bang.literal_syntax();
|
||||||
let mut args = StaticVec::new_const();
|
let mut args = FnArgsVec::new_const();
|
||||||
args.push(fn_call);
|
args.push(fn_call);
|
||||||
|
|
||||||
let not_base = FnCallExpr {
|
let not_base = FnCallExpr {
|
||||||
@ -3708,7 +3708,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let num_externals = externals.len();
|
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);
|
args.push(fn_expr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user