Move ErrorAssignmentToUnknownLHS to ParseError.

This commit is contained in:
Stephen Chung 2020-10-28 10:26:36 +08:00
parent 4b087d0e69
commit 30e11f137b
5 changed files with 19 additions and 33 deletions

View File

@ -16,6 +16,7 @@ Breaking changes
----------------
* Custom syntax can no longer start with a keyword (even a _reserved_ one), even if it has been disabled. That is to avoid breaking scripts later when the keyword is no longer disabled.
* `EvalAltResult::ErrorAssignmentToUnknownLHS` is moved to `ParseError::AssignmentToInvalidLHS`. `ParseError::AssignmentToCopy` is removed.
New features
------------

View File

@ -302,26 +302,19 @@ impl<'a> Target<'a> {
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, ch) => {
let char_value = ch.clone();
self.set_value((char_value, Position::none()), Position::none())
.unwrap();
self.set_value((char_value, Position::none())).unwrap();
}
}
}
/// Update the value of the `Target`.
#[cfg(any(not(feature = "no_object"), not(feature = "no_index")))]
pub fn set_value(
&mut self,
new_val: (Dynamic, Position),
target_pos: Position,
) -> Result<(), Box<EvalAltResult>> {
pub fn set_value(&mut self, new_val: (Dynamic, Position)) -> Result<(), Box<EvalAltResult>> {
match self {
Self::Ref(r) => **r = new_val.0,
#[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "no_object"))]
Self::LockGuard((r, _)) => **r = new_val.0,
Self::Value(_) => {
return EvalAltResult::ErrorAssignmentToUnknownLHS(target_pos).into();
}
Self::Value(_) => unreachable!(),
#[cfg(not(feature = "no_index"))]
Self::StringChar(string, index, _) if string.is::<ImmutableString>() => {
let mut s = string.write_lock::<ImmutableString>().unwrap();
@ -924,7 +917,7 @@ impl Engine {
{
// Indexed value is a reference - update directly
Ok(ref mut obj_ptr) => {
obj_ptr.set_value(new_val.unwrap(), rhs.position())?;
obj_ptr.set_value(new_val.unwrap())?;
None
}
Err(err) => match *err {
@ -992,7 +985,7 @@ impl Engine {
let mut val = self
.get_indexed_mut(state, lib, target, index, *pos, true, false, level)?;
val.set_value(new_val.unwrap(), rhs.position())?;
val.set_value(new_val.unwrap())?;
Ok((Default::default(), true))
}
// {xxx:map}.id
@ -1219,9 +1212,7 @@ impl Engine {
.map_err(|err| err.fill_position(*op_pos))
}
// {expr}.??? = ??? or {expr}[???] = ???
expr if new_val.is_some() => {
return EvalAltResult::ErrorAssignmentToUnknownLHS(expr.position()).into();
}
_ if new_val.is_some() => unreachable!(),
// {expr}.??? or {expr}[???]
expr => {
let val = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
@ -1803,10 +1794,8 @@ impl Engine {
)?;
Ok(Default::default())
}
// Constant expression (should be caught during parsing)
expr if expr.is_constant() => unreachable!(),
// Syntax error
expr => EvalAltResult::ErrorAssignmentToUnknownLHS(expr.position()).into(),
// Non-lvalue expression (should be caught during parsing)
_ => unreachable!(),
}
}

View File

@ -138,10 +138,11 @@ pub enum ParseErrorType {
///
/// Never appears under the `no_module` feature.
WrongExport,
/// Assignment to a copy of a value.
AssignmentToCopy,
/// Assignment to an a constant variable. Wrapped value is the constant variable name.
AssignmentToConstant(String),
/// Assignment to an inappropriate LHS (left-hand-side) expression.
/// Wrapped value is the error message (if any).
AssignmentToInvalidLHS(String),
/// Expression exceeding the maximum levels of complexity.
///
/// Never appears under the `unchecked` feature.
@ -183,8 +184,8 @@ impl ParseErrorType {
Self::WrongFnDefinition => "Function definitions must be at global level and cannot be inside a block or another function",
Self::DuplicatedExport(_) => "Duplicated variable/function in export statement",
Self::WrongExport => "Export statement can only appear at global level",
Self::AssignmentToCopy => "Only a copy of the value is change with this assignment",
Self::AssignmentToConstant(_) => "Cannot assign to a constant value",
Self::AssignmentToInvalidLHS(_) => "Expression cannot be assigned to",
Self::ExprTooDeep => "Expression exceeds maximum complexity",
Self::LiteralTooLarge(_, _) => "Literal exceeds maximum limit",
Self::LoopBreak => "Break statement should only be used inside a loop"
@ -233,6 +234,10 @@ impl fmt::Display for ParseErrorType {
Self::AssignmentToConstant(s) if s.is_empty() => f.write_str(self.desc()),
Self::AssignmentToConstant(s) => write!(f, "Cannot assign to constant '{}'", s),
Self::AssignmentToInvalidLHS(s) if s.is_empty() => f.write_str(self.desc()),
Self::AssignmentToInvalidLHS(s) => f.write_str(s),
Self::LiteralTooLarge(typ, max) => {
write!(f, "{} exceeds the maximum limit ({})", typ, max)
}

View File

@ -2280,7 +2280,7 @@ fn make_assignment_stmt<'a>(
}
}
// expr[???] = rhs, expr.??? = rhs
_ => Err(PERR::AssignmentToCopy.into_err(x.lhs.position())),
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(x.lhs.position())),
},
// const_expr = rhs
expr if expr.is_constant() => {
@ -2291,7 +2291,7 @@ fn make_assignment_stmt<'a>(
Err(PERR::BadInput("Possibly a typo of '=='?".to_string()).into_err(pos))
}
// expr = rhs
_ => Err(PERR::AssignmentToCopy.into_err(lhs.position())),
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(lhs.position())),
}
}

View File

@ -71,8 +71,6 @@ pub enum EvalAltResult {
ErrorFor(Position),
/// Data race detected when accessing a variable. Wrapped value is the variable name.
ErrorDataRace(String, Position),
/// Assignment to an inappropriate LHS (left-hand-side) expression.
ErrorAssignmentToUnknownLHS(Position),
/// Assignment to a constant variable. Wrapped value is the variable name.
ErrorAssignmentToConstant(String, Position),
/// Inappropriate property access. Wrapped value is the property name.
@ -129,9 +127,6 @@ impl EvalAltResult {
Self::ErrorVariableNotFound(_, _) => "Variable not found",
Self::ErrorModuleNotFound(_, _) => "Module not found",
Self::ErrorDataRace(_, _) => "Data race detected when accessing variable",
Self::ErrorAssignmentToUnknownLHS(_) => {
"Assignment to an unsupported left-hand side expression"
}
Self::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect",
Self::ErrorInExpr(_) => "Malformed 'in' expression",
@ -185,7 +180,6 @@ impl fmt::Display for EvalAltResult {
Self::ErrorIndexingType(_, _)
| Self::ErrorUnboundThis(_)
| Self::ErrorFor(_)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorInExpr(_)
| Self::ErrorDotExpr(_, _)
| Self::ErrorTooManyOperations(_)
@ -293,7 +287,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, _)
| Self::ErrorModuleNotFound(_, _)
| Self::ErrorDataRace(_, _)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorAssignmentToConstant(_, _)
| Self::ErrorMismatchOutputType(_, _, _)
| Self::ErrorInExpr(_)
@ -329,7 +322,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, pos)
| Self::ErrorModuleNotFound(_, pos)
| Self::ErrorDataRace(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos)
@ -364,7 +356,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, pos)
| Self::ErrorModuleNotFound(_, pos)
| Self::ErrorDataRace(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos)