Add comments and minor refactor.
This commit is contained in:
parent
f5c7d7cd0d
commit
ce121ed6af
@ -703,6 +703,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Chain-evaluate a dot/index chain.
|
/// Chain-evaluate a dot/index chain.
|
||||||
|
/// Index values are pre-calculated and stored in `idx_list`.
|
||||||
|
/// Any spill-overs are stored in `idx_more`.
|
||||||
fn eval_dot_index_chain_helper(
|
fn eval_dot_index_chain_helper(
|
||||||
&self,
|
&self,
|
||||||
fn_lib: Option<&FunctionsLib>,
|
fn_lib: Option<&FunctionsLib>,
|
||||||
@ -730,18 +732,18 @@ impl Engine {
|
|||||||
|
|
||||||
// Pop the last index value
|
// Pop the last index value
|
||||||
let mut idx_val;
|
let mut idx_val;
|
||||||
let mut idx_fixed = idx_list;
|
let mut idx_list = idx_list;
|
||||||
|
|
||||||
if let Some(val) = idx_more.pop() {
|
if let Some(val) = idx_more.pop() {
|
||||||
// Values in variable list
|
// Values in variable list
|
||||||
idx_val = val;
|
idx_val = val;
|
||||||
} else {
|
} else {
|
||||||
// No more value in variable list, pop from fixed list
|
// No more value in variable list, pop from fixed list
|
||||||
let len = idx_fixed.len();
|
let len = idx_list.len();
|
||||||
let splits = idx_fixed.split_at_mut(len - 1);
|
let splits = idx_list.split_at_mut(len - 1);
|
||||||
|
|
||||||
idx_val = mem::replace(splits.1.get_mut(0).unwrap(), ().into());
|
idx_val = mem::replace(splits.1.get_mut(0).unwrap(), ().into());
|
||||||
idx_fixed = splits.0;
|
idx_list = splits.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_index {
|
if is_index {
|
||||||
@ -754,7 +756,7 @@ impl Engine {
|
|||||||
|
|
||||||
let indexed_val = self.get_indexed_mut(obj, idx_val, idx.position(), op_pos, false)?;
|
let indexed_val = self.get_indexed_mut(obj, idx_val, idx.position(), op_pos, false)?;
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
fn_lib, indexed_val, idx_rhs.as_ref(), idx_fixed, idx_more, is_index, *pos, level, new_val
|
fn_lib, indexed_val, idx_rhs.as_ref(), idx_list, idx_more, is_index, *pos, level, new_val
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// xxx[rhs] = new_val
|
// xxx[rhs] = new_val
|
||||||
@ -780,17 +782,19 @@ impl Engine {
|
|||||||
// TODO - Remove assumption of side effects by checking whether the first parameter is &mut
|
// TODO - Remove assumption of side effects by checking whether the first parameter is &mut
|
||||||
self.exec_fn_call(fn_lib, fn_name, &mut args, def_val, *pos, 0).map(|v| (v, true))
|
self.exec_fn_call(fn_lib, fn_name, &mut args, def_val, *pos, 0).map(|v| (v, true))
|
||||||
}
|
}
|
||||||
|
// {xxx:map}.id = ???
|
||||||
|
Expr::Property(id, pos) if obj.is::<Map>() && new_val.is_some() => {
|
||||||
|
let mut indexed_val =
|
||||||
|
self.get_indexed_mut(obj, id.to_string().into(), *pos, op_pos, true)?;
|
||||||
|
indexed_val.set_value(new_val.unwrap(), rhs.position())?;
|
||||||
|
Ok((().into(), true))
|
||||||
|
}
|
||||||
// {xxx:map}.id
|
// {xxx:map}.id
|
||||||
Expr::Property(id, pos) if obj.is::<Map>() => {
|
Expr::Property(id, pos) if obj.is::<Map>() => {
|
||||||
let mut indexed_val =
|
let indexed_val =
|
||||||
self.get_indexed_mut(obj, id.to_string().into(), *pos, op_pos, new_val.is_some())?;
|
self.get_indexed_mut(obj, id.to_string().into(), *pos, op_pos, false)?;
|
||||||
if let Some(new_val) = new_val {
|
|
||||||
indexed_val.set_value(new_val, rhs.position())?;
|
|
||||||
Ok((().into(), true))
|
|
||||||
} else {
|
|
||||||
Ok((indexed_val.into_dynamic(), false))
|
Ok((indexed_val.into_dynamic(), false))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// xxx.id = ???
|
// xxx.id = ???
|
||||||
Expr::Property(id, pos) if new_val.is_some() => {
|
Expr::Property(id, pos) if new_val.is_some() => {
|
||||||
let fn_name = make_setter(id);
|
let fn_name = make_setter(id);
|
||||||
@ -819,7 +823,7 @@ impl Engine {
|
|||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
fn_lib, indexed_val, dot_rhs, idx_fixed, idx_more, is_index, *pos, level, new_val
|
fn_lib, indexed_val, dot_rhs, idx_list, idx_more, is_index, *pos, level, new_val
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// xxx.idx_lhs[idx_expr]
|
// xxx.idx_lhs[idx_expr]
|
||||||
@ -830,7 +834,7 @@ impl Engine {
|
|||||||
let mut buf: Dynamic = ().into();
|
let mut buf: Dynamic = ().into();
|
||||||
let mut args = [obj, &mut buf];
|
let mut args = [obj, &mut buf];
|
||||||
|
|
||||||
let mut indexed_val = if let Expr::Property(id, pos) = dot_lhs.as_ref() {
|
let indexed_val = &mut (if let Expr::Property(id, pos) = dot_lhs.as_ref() {
|
||||||
let fn_name = make_getter(id);
|
let fn_name = make_getter(id);
|
||||||
self.exec_fn_call(fn_lib, &fn_name, &mut args[..1], None, *pos, 0)?
|
self.exec_fn_call(fn_lib, &fn_name, &mut args[..1], None, *pos, 0)?
|
||||||
} else {
|
} else {
|
||||||
@ -839,16 +843,16 @@ impl Engine {
|
|||||||
"".to_string(),
|
"".to_string(),
|
||||||
rhs.position(),
|
rhs.position(),
|
||||||
)));
|
)));
|
||||||
};
|
});
|
||||||
let (result, changed) = self.eval_dot_index_chain_helper(
|
let (result, changed) = self.eval_dot_index_chain_helper(
|
||||||
fn_lib, (&mut indexed_val).into(), dot_rhs, idx_fixed, idx_more, is_index, *pos, level, new_val
|
fn_lib, indexed_val.into(), dot_rhs, idx_list, idx_more, is_index, *pos, level, new_val
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Feed the value back via a setter just in case it has been updated
|
// Feed the value back via a setter just in case it has been updated
|
||||||
if changed {
|
if changed {
|
||||||
if let Expr::Property(id, pos) = dot_lhs.as_ref() {
|
if let Expr::Property(id, pos) = dot_lhs.as_ref() {
|
||||||
let fn_name = make_setter(id);
|
let fn_name = make_setter(id);
|
||||||
args[1] = &mut indexed_val;
|
args[1] = indexed_val;
|
||||||
self.exec_fn_call(fn_lib, &fn_name, &mut args, None, *pos, 0)?;
|
self.exec_fn_call(fn_lib, &fn_name, &mut args, None, *pos, 0)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -864,7 +868,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a dot/index chain
|
/// Evaluate a dot/index chain.
|
||||||
fn eval_dot_index_chain(
|
fn eval_dot_index_chain(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
@ -945,6 +949,11 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a chain of indexes and store the results in a list.
|
||||||
|
/// The first few results are stored in the array `list` which is of fixed length.
|
||||||
|
/// Any spill-overs are stored in `more`, which is dynamic.
|
||||||
|
/// The fixed length array is used to avoid an allocation in the overwhelming cases of just a few levels of indexing.
|
||||||
|
/// The total number of values is returned.
|
||||||
fn eval_indexed_chain(
|
fn eval_indexed_chain(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
@ -955,7 +964,7 @@ impl Engine {
|
|||||||
size: usize,
|
size: usize,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<usize, Box<EvalAltResult>> {
|
) -> Result<usize, Box<EvalAltResult>> {
|
||||||
let size = match expr {
|
match expr {
|
||||||
Expr::FunctionCall(_, arg_exprs, _, _) => {
|
Expr::FunctionCall(_, arg_exprs, _, _) => {
|
||||||
let arg_values = arg_exprs
|
let arg_values = arg_exprs
|
||||||
.iter()
|
.iter()
|
||||||
@ -967,21 +976,21 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
more.push(arg_values.into());
|
more.push(arg_values.into());
|
||||||
}
|
}
|
||||||
size + 1
|
Ok(size + 1)
|
||||||
}
|
}
|
||||||
Expr::Property(_, _) => {
|
Expr::Property(_, _) => {
|
||||||
// Placeholder
|
// Store a placeholder - no need to copy the property name
|
||||||
if size < list.len() {
|
if size < list.len() {
|
||||||
list[size] = ().into();
|
list[size] = ().into();
|
||||||
} else {
|
} else {
|
||||||
more.push(().into());
|
more.push(().into());
|
||||||
}
|
}
|
||||||
size + 1
|
Ok(size + 1)
|
||||||
}
|
}
|
||||||
Expr::Index(lhs, rhs, _) | Expr::Dot(lhs, rhs, _) => {
|
Expr::Index(lhs, rhs, _) | Expr::Dot(lhs, rhs, _) => {
|
||||||
// Evaluate in left-to-right order
|
// Evaluate in left-to-right order
|
||||||
let lhs_val = match lhs.as_ref() {
|
let lhs_val = match lhs.as_ref() {
|
||||||
Expr::Property(_, _) => ().into(), // Placeholder
|
Expr::Property(_, _) => ().into(), // Store a placeholder in case of a property
|
||||||
_ => self.eval_expr(scope, fn_lib, lhs, level)?,
|
_ => self.eval_expr(scope, fn_lib, lhs, level)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -993,7 +1002,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
more.push(lhs_val);
|
more.push(lhs_val);
|
||||||
}
|
}
|
||||||
size + 1
|
Ok(size + 1)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let val = self.eval_expr(scope, fn_lib, expr, level)?;
|
let val = self.eval_expr(scope, fn_lib, expr, level)?;
|
||||||
@ -1002,10 +1011,9 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
more.push(val);
|
more.push(val);
|
||||||
}
|
}
|
||||||
size + 1
|
Ok(size + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
Ok(size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the value at the indexed position of a base type
|
/// Get the value at the indexed position of a base type
|
||||||
|
Loading…
Reference in New Issue
Block a user