Avoid copying indexed value if not necessary.

This commit is contained in:
Stephen Chung 2020-04-16 12:08:28 +08:00
parent 090217e1cd
commit 4f2350734f

View File

@ -519,12 +519,12 @@ impl Engine<'_> {
} }
if let Some(prop) = extract_prop_from_setter(fn_name) { if let Some(prop) = extract_prop_from_setter(fn_name) {
let value = args[1].clone(); let (arg, value) = args.split_at_mut(0);
return match args[0] { return match arg[0] {
// Map property update // Map property update
Dynamic(Union::Map(map)) => { Dynamic(Union::Map(map)) => {
map.insert(prop.to_string(), value); map.insert(prop.to_string(), value[0].clone());
Ok(Dynamic::from_unit()) Ok(Dynamic::from_unit())
} }
@ -588,7 +588,7 @@ impl Engine<'_> {
// xxx.idx_lhs[idx_expr] // xxx.idx_lhs[idx_expr]
Expr::Index(idx_lhs, idx_expr, op_pos) => { Expr::Index(idx_lhs, idx_expr, op_pos) => {
let value = match idx_lhs.as_ref() { let lhs_value = match idx_lhs.as_ref() {
// xxx.id[idx_expr] // xxx.id[idx_expr]
Expr::Property(id, pos) => { Expr::Property(id, pos) => {
let mut args = [target.get_mut(scope)]; let mut args = [target.get_mut(scope)];
@ -596,6 +596,7 @@ impl Engine<'_> {
} }
// xxx.???[???][idx_expr] // xxx.???[???][idx_expr]
Expr::Index(_, _, _) => { Expr::Index(_, _, _) => {
// Chain the indexing
self.get_dot_val_helper(scope, fn_lib, target, idx_lhs, level)? self.get_dot_val_helper(scope, fn_lib, target, idx_lhs, level)?
} }
// Syntax error // Syntax error
@ -607,7 +608,7 @@ impl Engine<'_> {
} }
}; };
self.get_indexed_value(scope, fn_lib, &value, idx_expr, *op_pos, level) self.get_indexed_value(scope, fn_lib, &lhs_value, idx_expr, *op_pos, level, false)
.map(|(val, _)| val) .map(|(val, _)| val)
} }
@ -643,7 +644,7 @@ impl Engine<'_> {
} }
}; };
self.get_indexed_value(scope, fn_lib, &val, idx_expr, *op_pos, level) self.get_indexed_value(scope, fn_lib, &val, idx_expr, *op_pos, level, false)
.and_then(|(mut val, _)| { .and_then(|(mut val, _)| {
self.get_dot_val_helper(scope, fn_lib, (&mut val).into(), rhs, level) self.get_dot_val_helper(scope, fn_lib, (&mut val).into(), rhs, level)
}) })
@ -744,6 +745,7 @@ impl Engine<'_> {
idx_expr: &Expr, idx_expr: &Expr,
op_pos: Position, op_pos: Position,
level: usize, level: usize,
only_index: bool,
) -> Result<(Dynamic, IndexValue), EvalAltResult> { ) -> Result<(Dynamic, IndexValue), EvalAltResult> {
let idx_pos = idx_expr.position(); let idx_pos = idx_expr.position();
let type_name = self.map_type_name(val.type_name()); let type_name = self.map_type_name(val.type_name());
@ -756,13 +758,22 @@ impl Engine<'_> {
.as_int() .as_int()
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?; .map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?;
return if index >= 0 { if index >= 0 {
arr.get(index as usize) arr.get(index as usize)
.map(|v| (v.clone(), IndexValue::from_num(index))) .map(|v| {
(
if only_index {
Dynamic::from_unit()
} else {
v.clone()
},
IndexValue::from_num(index),
)
})
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos)) .ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos))
} else { } else {
Err(EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos)) Err(EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos))
}; }
} }
Union::Map(map) => { Union::Map(map) => {
@ -772,12 +783,18 @@ impl Engine<'_> {
.take_string() .take_string()
.map_err(|_| EvalAltResult::ErrorStringIndexExpr(idx_expr.position()))?; .map_err(|_| EvalAltResult::ErrorStringIndexExpr(idx_expr.position()))?;
return Ok(( Ok((
map.get(&index) map.get(&index)
.cloned() .map(|v| {
if only_index {
Dynamic::from_unit()
} else {
v.clone()
}
})
.unwrap_or_else(|| Dynamic::from_unit()), .unwrap_or_else(|| Dynamic::from_unit()),
IndexValue::from_str(index), IndexValue::from_str(index),
)); ))
} }
Union::Str(s) => { Union::Str(s) => {
@ -787,7 +804,7 @@ impl Engine<'_> {
.as_int() .as_int()
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?; .map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?;
return if index >= 0 { if index >= 0 {
s.chars() s.chars()
.nth(index as usize) .nth(index as usize)
.map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index))) .map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index)))
@ -800,7 +817,7 @@ impl Engine<'_> {
index, index,
idx_pos, idx_pos,
)) ))
}; }
} }
// Error - cannot be indexed // Error - cannot be indexed
@ -827,7 +844,7 @@ impl Engine<'_> {
let (ScopeSource { typ, index, .. }, val) = let (ScopeSource { typ, index, .. }, val) =
Self::search_scope(scope, &id, lhs.position())?; Self::search_scope(scope, &id, lhs.position())?;
let (val, idx) = let (val, idx) =
self.get_indexed_value(scope, fn_lib, &val, idx_expr, op_pos, level)?; self.get_indexed_value(scope, fn_lib, &val, idx_expr, op_pos, level, false)?;
Ok(( Ok((
Some(ScopeSource { Some(ScopeSource {
@ -843,7 +860,7 @@ impl Engine<'_> {
// (expr)[idx_expr] // (expr)[idx_expr]
expr => { expr => {
let val = self.eval_expr(scope, fn_lib, expr, level)?; let val = self.eval_expr(scope, fn_lib, expr, level)?;
self.get_indexed_value(scope, fn_lib, &val, idx_expr, op_pos, level) self.get_indexed_value(scope, fn_lib, &val, idx_expr, op_pos, level, false)
.map(|(val, index)| (None, index, val)) .map(|(val, index)| (None, index, val))
} }
} }
@ -951,8 +968,9 @@ impl Engine<'_> {
let fn_name = make_getter(id); let fn_name = make_getter(id);
self.call_fn_raw(None, fn_lib, &fn_name, &mut [this_ptr], None, *pos, 0) self.call_fn_raw(None, fn_lib, &fn_name, &mut [this_ptr], None, *pos, 0)
.and_then(|val| { .and_then(|val| {
let (_, index) = self let (_, index) = self.get_indexed_value(
.get_indexed_value(scope, fn_lib, &val, idx_expr, *op_pos, level)?; scope, fn_lib, &val, idx_expr, *op_pos, level, true,
)?;
Self::update_indexed_value(val, index, new_val.0.clone(), new_val.1) Self::update_indexed_value(val, index, new_val.0.clone(), new_val.1)
}) })
@ -996,7 +1014,7 @@ impl Engine<'_> {
self.call_fn_raw(None, fn_lib, &fn_name, &mut [this_ptr], None, *pos, 0) self.call_fn_raw(None, fn_lib, &fn_name, &mut [this_ptr], None, *pos, 0)
.and_then(|v| { .and_then(|v| {
let (mut value, index) = self.get_indexed_value( let (mut value, index) = self.get_indexed_value(
scope, fn_lib, &v, idx_expr, *op_pos, level, scope, fn_lib, &v, idx_expr, *op_pos, level, false,
)?; )?;
let val_pos = new_val.1; let val_pos = new_val.1;