Refine indexer set.
This commit is contained in:
parent
5873bccd50
commit
af2f8acb5d
@ -721,8 +721,9 @@ impl Engine {
|
|||||||
Expr::Dot(x) | Expr::Index(x) => {
|
Expr::Dot(x) | Expr::Index(x) => {
|
||||||
let (idx, expr, pos) = x.as_ref();
|
let (idx, expr, pos) = x.as_ref();
|
||||||
let idx_pos = idx.position();
|
let idx_pos = idx.position();
|
||||||
let obj_ptr = &mut self
|
let obj_ptr = &mut self.get_indexed_mut(
|
||||||
.get_indexed_mut(state, lib, target, idx_val, idx_pos, false, level)?;
|
state, lib, target, idx_val, idx_pos, false, true, level,
|
||||||
|
)?;
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
state, lib, this_ptr, obj_ptr, expr, idx_values, next_chain, level,
|
state, lib, this_ptr, obj_ptr, expr, idx_values, next_chain, level,
|
||||||
@ -735,14 +736,9 @@ impl Engine {
|
|||||||
let mut idx_val2 = idx_val.clone();
|
let mut idx_val2 = idx_val.clone();
|
||||||
|
|
||||||
// `call_setter` is introduced to bypass double mutable borrowing of target
|
// `call_setter` is introduced to bypass double mutable borrowing of target
|
||||||
let mut call_setter = match self
|
let _call_setter = match self
|
||||||
.get_indexed_mut(state, lib, target, idx_val, pos, true, level)
|
.get_indexed_mut(state, lib, target, idx_val, pos, true, false, level)
|
||||||
{
|
{
|
||||||
// Indexed value is an owned value - the only possibility is a value from an indexer.
|
|
||||||
// Try to call an index setter to update it back, but no need to raise an error
|
|
||||||
// if the indexer is read-only.
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Ok(obj_ptr) if obj_ptr.is_value() => Some((false, _new_val.unwrap())),
|
|
||||||
// Indexed value is a reference - update directly
|
// Indexed value is a reference - update directly
|
||||||
Ok(ref mut obj_ptr) => {
|
Ok(ref mut obj_ptr) => {
|
||||||
obj_ptr
|
obj_ptr
|
||||||
@ -753,37 +749,42 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
Err(err) => match *err {
|
Err(err) => match *err {
|
||||||
// No index getter - try to call an index setter
|
// No index getter - try to call an index setter
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
EvalAltResult::ErrorIndexingType(_, _) => {
|
EvalAltResult::ErrorIndexingType(_, _) => {
|
||||||
// Raise error if there is no index getter nor setter
|
// Raise error if there is no index getter nor setter
|
||||||
Some((true, _new_val.unwrap()))
|
Some(_new_val.unwrap())
|
||||||
}
|
}
|
||||||
// Any other error - return
|
// Any other error - return
|
||||||
err => return Err(Box::new(err)),
|
err => return Err(Box::new(err)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((must_have_setter, ref mut new_val)) = call_setter {
|
#[cfg(not(feature = "no_index"))]
|
||||||
let args = &mut [target.as_mut(), &mut idx_val2, new_val];
|
if let Some(mut new_val) = _call_setter {
|
||||||
|
let val = target.as_mut();
|
||||||
|
let val_type_name = val.type_name();
|
||||||
|
let args = &mut [val, &mut idx_val2, &mut new_val];
|
||||||
|
|
||||||
match self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, None,
|
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, None,
|
||||||
level,
|
level,
|
||||||
) {
|
)
|
||||||
Ok(_) => (),
|
.map_err(|err| match *err {
|
||||||
Err(err) if !must_have_setter => match *err {
|
EvalAltResult::ErrorFunctionNotFound(_, _) => {
|
||||||
// If there is no index setter, no need to set it back because the indexer is read-only
|
EvalAltResult::ErrorIndexingType(
|
||||||
EvalAltResult::ErrorFunctionNotFound(_, _) => (),
|
self.map_type_name(val_type_name).into(),
|
||||||
_ => return Err(err),
|
Position::none(),
|
||||||
},
|
)
|
||||||
err => return err,
|
}
|
||||||
}
|
err => err,
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
}
|
}
|
||||||
// xxx[rhs]
|
// xxx[rhs]
|
||||||
_ => self
|
_ => self
|
||||||
.get_indexed_mut(state, lib, target, idx_val, pos, false, level)
|
.get_indexed_mut(state, lib, target, idx_val, pos, false, true, level)
|
||||||
.map(|v| (v.clone_into_dynamic(), false)),
|
.map(|v| (v.clone_into_dynamic(), false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -806,8 +807,8 @@ impl Engine {
|
|||||||
Expr::Property(x) if target.is::<Map>() && _new_val.is_some() => {
|
Expr::Property(x) if target.is::<Map>() && _new_val.is_some() => {
|
||||||
let ((prop, _, _), pos) = x.as_ref();
|
let ((prop, _, _), pos) = x.as_ref();
|
||||||
let index = prop.clone().into();
|
let index = prop.clone().into();
|
||||||
let mut val =
|
let mut val = self
|
||||||
self.get_indexed_mut(state, lib, target, index, *pos, true, level)?;
|
.get_indexed_mut(state, lib, target, index, *pos, true, false, level)?;
|
||||||
|
|
||||||
val.set_value(_new_val.unwrap())
|
val.set_value(_new_val.unwrap())
|
||||||
.map_err(|err| err.new_position(rhs.position()))?;
|
.map_err(|err| err.new_position(rhs.position()))?;
|
||||||
@ -817,8 +818,9 @@ impl Engine {
|
|||||||
Expr::Property(x) if target.is::<Map>() => {
|
Expr::Property(x) if target.is::<Map>() => {
|
||||||
let ((prop, _, _), pos) = x.as_ref();
|
let ((prop, _, _), pos) = x.as_ref();
|
||||||
let index = prop.clone().into();
|
let index = prop.clone().into();
|
||||||
let val =
|
let val = self.get_indexed_mut(
|
||||||
self.get_indexed_mut(state, lib, target, index, *pos, false, level)?;
|
state, lib, target, index, *pos, false, false, level,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok((val.clone_into_dynamic(), false))
|
Ok((val.clone_into_dynamic(), false))
|
||||||
}
|
}
|
||||||
@ -852,7 +854,9 @@ impl Engine {
|
|||||||
Expr::Property(p) => {
|
Expr::Property(p) => {
|
||||||
let ((prop, _, _), pos) = p.as_ref();
|
let ((prop, _, _), pos) = p.as_ref();
|
||||||
let index = prop.clone().into();
|
let index = prop.clone().into();
|
||||||
self.get_indexed_mut(state, lib, target, index, *pos, false, level)?
|
self.get_indexed_mut(
|
||||||
|
state, lib, target, index, *pos, false, true, level,
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
@ -1125,6 +1129,7 @@ impl Engine {
|
|||||||
mut _idx: Dynamic,
|
mut _idx: Dynamic,
|
||||||
idx_pos: Position,
|
idx_pos: Position,
|
||||||
_create: bool,
|
_create: bool,
|
||||||
|
_indexers: bool,
|
||||||
_level: usize,
|
_level: usize,
|
||||||
) -> Result<Target<'a>, Box<EvalAltResult>> {
|
) -> Result<Target<'a>, Box<EvalAltResult>> {
|
||||||
self.inc_operations(state)?;
|
self.inc_operations(state)?;
|
||||||
@ -1201,7 +1206,7 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ => {
|
_ if _indexers => {
|
||||||
let type_name = val.type_name();
|
let type_name = val.type_name();
|
||||||
let args = &mut [val, &mut _idx];
|
let args = &mut [val, &mut _idx];
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
@ -1216,7 +1221,6 @@ impl Engine {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "no_index", feature = "no_object"))]
|
|
||||||
_ => Err(Box::new(EvalAltResult::ErrorIndexingType(
|
_ => Err(Box::new(EvalAltResult::ErrorIndexingType(
|
||||||
self.map_type_name(val.type_name()).into(),
|
self.map_type_name(val.type_name()).into(),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
|
@ -1188,30 +1188,30 @@ pub fn run_builtin_op_assignment(
|
|||||||
let mut x = x.write_lock::<INT>().unwrap();
|
let mut x = x.write_lock::<INT>().unwrap();
|
||||||
let y = y.clone().cast::<INT>();
|
let y = y.clone().cast::<INT>();
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
if cfg!(not(feature = "unchecked")) {
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x = add(*x, y)?)),
|
"+=" => return Ok(Some(*x = add(*x, y)?)),
|
||||||
"-=" => return Ok(Some(*x = sub(*x, y)?)),
|
"-=" => return Ok(Some(*x = sub(*x, y)?)),
|
||||||
"*=" => return Ok(Some(*x = mul(*x, y)?)),
|
"*=" => return Ok(Some(*x = mul(*x, y)?)),
|
||||||
"/=" => return Ok(Some(*x = div(*x, y)?)),
|
"/=" => return Ok(Some(*x = div(*x, y)?)),
|
||||||
"%=" => return Ok(Some(*x = modulo(*x, y)?)),
|
"%=" => return Ok(Some(*x = modulo(*x, y)?)),
|
||||||
"~=" => return Ok(Some(*x = pow_i_i(*x, y)?)),
|
"~=" => return Ok(Some(*x = pow_i_i(*x, y)?)),
|
||||||
">>=" => return Ok(Some(*x = shr(*x, y)?)),
|
">>=" => return Ok(Some(*x = shr(*x, y)?)),
|
||||||
"<<=" => return Ok(Some(*x = shl(*x, y)?)),
|
"<<=" => return Ok(Some(*x = shl(*x, y)?)),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
#[cfg(feature = "unchecked")]
|
match op {
|
||||||
match op {
|
"+=" => return Ok(Some(*x += y)),
|
||||||
"+=" => return Ok(Some(*x += y)),
|
"-=" => return Ok(Some(*x -= y)),
|
||||||
"-=" => return Ok(Some(*x -= y)),
|
"*=" => return Ok(Some(*x *= y)),
|
||||||
"*=" => return Ok(Some(*x *= y)),
|
"/=" => return Ok(Some(*x /= y)),
|
||||||
"/=" => return Ok(Some(*x /= y)),
|
"%=" => return Ok(Some(*x %= y)),
|
||||||
"%=" => return Ok(Some(*x %= y)),
|
"~=" => return Ok(Some(*x = pow_i_i_u(*x, y)?)),
|
||||||
"~=" => return Ok(Some(*x = pow_i_i_u(*x, y)?)),
|
">>=" => return Ok(Some(*x = shr_u(*x, y)?)),
|
||||||
">>=" => return Ok(Some(*x = shr_u(*x, y)?)),
|
"<<=" => return Ok(Some(*x = shl_u(*x, y)?)),
|
||||||
"<<=" => return Ok(Some(*x = shl_u(*x, y)?)),
|
_ => (),
|
||||||
_ => (),
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
|
Loading…
Reference in New Issue
Block a user