Fix no_index and no_object.

This commit is contained in:
Stephen Chung 2020-07-31 23:37:30 +08:00
parent 60891e694f
commit 5873bccd50

View File

@ -734,69 +734,49 @@ impl Engine {
_ if _new_val.is_some() => { _ if _new_val.is_some() => {
let mut idx_val2 = idx_val.clone(); let mut idx_val2 = idx_val.clone();
// `next` 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
.get_indexed_mut(state, lib, target, idx_val, pos, true, 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"))] #[cfg(not(feature = "no_index"))]
let mut next: Option<(u8, Dynamic)>; Ok(obj_ptr) if obj_ptr.is_value() => Some((false, _new_val.unwrap())),
match self.get_indexed_mut(state, lib, target, idx_val, pos, true, level) {
// Indexed value is an owned value - the only possibility is an indexer
// Try to call an index setter
#[cfg(not(feature = "no_index"))]
Ok(obj_ptr) if obj_ptr.is_value() => {
next = Some((1, _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
.set_value(_new_val.unwrap()) .set_value(_new_val.unwrap())
.map_err(|err| err.new_position(rhs.position()))?; .map_err(|err| err.new_position(rhs.position()))?;
#[cfg(not(feature = "no_index"))] None
{
next = None;
}
} }
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(_, _) => {
next = Some((2, _new_val.unwrap())); // Raise error if there is no index getter nor setter
Some((true, _new_val.unwrap()))
} }
// Error // Any other error - return
err => return Err(Box::new(err)), err => return Err(Box::new(err)),
}, },
}; };
#[cfg(not(feature = "no_index"))] if let Some((must_have_setter, ref mut new_val)) = call_setter {
match &mut next { let args = &mut [target.as_mut(), &mut idx_val2, new_val];
// next step is custom index setter call
Some((1, _new_val)) => {
let args = &mut [target.as_mut(), &mut idx_val2, _new_val];
self.exec_fn_call( match self.exec_fn_call(
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None, None,
None, level, level,
) ) {
.or_else(|err| match *err { Ok(_) => (),
Err(err) if !must_have_setter => match *err {
// If there is no index setter, no need to set it back because the indexer is read-only // If there is no index setter, no need to set it back because the indexer is read-only
EvalAltResult::ErrorFunctionNotFound(_, _) => { EvalAltResult::ErrorFunctionNotFound(_, _) => (),
Ok(Default::default()) _ => return Err(err),
},
err => return err,
} }
_ => Err(err),
})?;
}
// next step is custom index setter call in case of error
Some((2, _new_val)) => {
let args = &mut [target.as_mut(), &mut idx_val2, _new_val];
self.exec_fn_call(
state, lib, FN_IDX_SET, 0, args, is_ref, true, false, None,
None, level,
)?;
}
None => (),
_ => unreachable!(),
} }
Ok(Default::default()) Ok(Default::default())