FIX - fixes panic when constant array is assigned to. Refine README section on constants.

This commit is contained in:
Stephen Chung
2020-03-14 19:46:44 +08:00
parent 504fd56f1f
commit 26bdc8ba08
5 changed files with 161 additions and 69 deletions

View File

@@ -372,16 +372,26 @@ impl Engine<'_> {
let val = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
if let Some((id, src_idx)) = src {
Self::update_indexed_var_in_scope(
src_type,
scope,
id,
src_idx,
idx,
target,
idx_lhs.position(),
)?;
if let Some((id, var_type, src_idx)) = src {
match var_type {
VariableType::Constant => {
return Err(EvalAltResult::ErrorAssignmentToConstant(
id.to_string(),
idx_lhs.position(),
));
}
VariableType::Normal => {
Self::update_indexed_var_in_scope(
src_type,
scope,
id,
src_idx,
idx,
target,
dot_rhs.position(),
)?;
}
}
}
val
@@ -477,7 +487,15 @@ impl Engine<'_> {
lhs: &'a Expr,
idx_expr: &Expr,
idx_pos: Position,
) -> Result<(IndexSourceType, Option<(&'a str, usize)>, usize, Dynamic), EvalAltResult> {
) -> Result<
(
IndexSourceType,
Option<(&'a str, VariableType, usize)>,
usize,
Dynamic,
),
EvalAltResult,
> {
let idx = self.eval_index_value(scope, idx_expr)?;
match lhs {
@@ -488,8 +506,13 @@ impl Engine<'_> {
|val| self.get_indexed_value(&val, idx, idx_expr.position(), idx_pos),
lhs.position(),
)
.map(|(src_idx, _, (val, src_type))| {
(src_type, Some((id.as_str(), src_idx)), idx as usize, val)
.map(|(src_idx, var_type, (val, src_type))| {
(
src_type,
Some((id.as_str(), var_type, src_idx)),
idx as usize,
val,
)
}),
// (expr)[idx_expr]
@@ -739,16 +762,20 @@ impl Engine<'_> {
self.set_dot_val_helper(scope, target.as_mut(), dot_rhs, new_val, val_pos);
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
if let Some((id, src_idx)) = src {
Self::update_indexed_var_in_scope(
src_type,
scope,
id,
src_idx,
idx,
target,
lhs.position(),
)?;
if let Some((id, var_type, src_idx)) = src {
match var_type {
VariableType::Constant => {
return Err(EvalAltResult::ErrorAssignmentToConstant(
id.to_string(),
lhs.position(),
));
}
VariableType::Normal => {
Self::update_indexed_var_in_scope(
src_type, scope, id, src_idx, idx, target, val_pos,
)?;
}
}
}
val
@@ -811,16 +838,24 @@ impl Engine<'_> {
let (src_type, src, idx, _) =
self.eval_index_expr(scope, idx_lhs, idx_expr, *idx_pos)?;
if let Some((id, src_idx)) = src {
Ok(Self::update_indexed_var_in_scope(
src_type,
scope,
&id,
src_idx,
idx,
rhs_val,
rhs.position(),
)?)
if let Some((id, var_type, src_idx)) = src {
match var_type {
VariableType::Constant => {
return Err(EvalAltResult::ErrorAssignmentToConstant(
id.to_string(),
idx_lhs.position(),
));
}
VariableType::Normal => Ok(Self::update_indexed_var_in_scope(
src_type,
scope,
&id,
src_idx,
idx,
rhs_val,
rhs.position(),
)?),
}
} else {
Err(EvalAltResult::ErrorAssignmentToUnknownLHS(
idx_lhs.position(),

View File

@@ -343,6 +343,8 @@ impl Expr {
| Expr::False(_)
| Expr::Unit(_) => true,
Expr::Array(expressions, _) => expressions.iter().all(Expr::is_constant),
#[cfg(not(feature = "no_float"))]
Expr::FloatConstant(_, _) => true,
@@ -1635,12 +1637,12 @@ fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, ParseEr
}
#[cfg(not(feature = "no_index"))]
Expr::Index(idx_lhs, _, _) if is_top => valid_assignment_chain(idx_lhs, true),
#[cfg(not(feature = "no_index"))]
Expr::Index(idx_lhs, _, _) if !is_top => Some(ParseError::new(
ParseErrorType::AssignmentToInvalidLHS,
idx_lhs.position(),
Expr::Index(idx_lhs, _, pos) => Some(ParseError::new(
match idx_lhs.as_ref() {
Expr::Index(_, _, _) => ParseErrorType::AssignmentToCopy,
_ => ParseErrorType::AssignmentToInvalidLHS,
},
*pos,
)),
Expr::Dot(dot_lhs, dot_rhs, _) => match dot_lhs.as_ref() {