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. * 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 New features
------------ ------------

View File

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

View File

@ -138,10 +138,11 @@ pub enum ParseErrorType {
/// ///
/// Never appears under the `no_module` feature. /// Never appears under the `no_module` feature.
WrongExport, WrongExport,
/// Assignment to a copy of a value.
AssignmentToCopy,
/// Assignment to an a constant variable. Wrapped value is the constant variable name. /// Assignment to an a constant variable. Wrapped value is the constant variable name.
AssignmentToConstant(String), 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. /// Expression exceeding the maximum levels of complexity.
/// ///
/// Never appears under the `unchecked` feature. /// 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::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::DuplicatedExport(_) => "Duplicated variable/function in export statement",
Self::WrongExport => "Export statement can only appear at global level", 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::AssignmentToConstant(_) => "Cannot assign to a constant value",
Self::AssignmentToInvalidLHS(_) => "Expression cannot be assigned to",
Self::ExprTooDeep => "Expression exceeds maximum complexity", Self::ExprTooDeep => "Expression exceeds maximum complexity",
Self::LiteralTooLarge(_, _) => "Literal exceeds maximum limit", Self::LiteralTooLarge(_, _) => "Literal exceeds maximum limit",
Self::LoopBreak => "Break statement should only be used inside a loop" 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) if s.is_empty() => f.write_str(self.desc()),
Self::AssignmentToConstant(s) => write!(f, "Cannot assign to constant '{}'", s), 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) => { Self::LiteralTooLarge(typ, max) => {
write!(f, "{} exceeds the maximum limit ({})", 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 // 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 // const_expr = rhs
expr if expr.is_constant() => { 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)) Err(PERR::BadInput("Possibly a typo of '=='?".to_string()).into_err(pos))
} }
// expr = rhs // 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), ErrorFor(Position),
/// Data race detected when accessing a variable. Wrapped value is the variable name. /// Data race detected when accessing a variable. Wrapped value is the variable name.
ErrorDataRace(String, Position), 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. /// Assignment to a constant variable. Wrapped value is the variable name.
ErrorAssignmentToConstant(String, Position), ErrorAssignmentToConstant(String, Position),
/// Inappropriate property access. Wrapped value is the property name. /// Inappropriate property access. Wrapped value is the property name.
@ -129,9 +127,6 @@ impl EvalAltResult {
Self::ErrorVariableNotFound(_, _) => "Variable not found", Self::ErrorVariableNotFound(_, _) => "Variable not found",
Self::ErrorModuleNotFound(_, _) => "Module not found", Self::ErrorModuleNotFound(_, _) => "Module not found",
Self::ErrorDataRace(_, _) => "Data race detected when accessing variable", 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::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect", Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect",
Self::ErrorInExpr(_) => "Malformed 'in' expression", Self::ErrorInExpr(_) => "Malformed 'in' expression",
@ -185,7 +180,6 @@ impl fmt::Display for EvalAltResult {
Self::ErrorIndexingType(_, _) Self::ErrorIndexingType(_, _)
| Self::ErrorUnboundThis(_) | Self::ErrorUnboundThis(_)
| Self::ErrorFor(_) | Self::ErrorFor(_)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorInExpr(_) | Self::ErrorInExpr(_)
| Self::ErrorDotExpr(_, _) | Self::ErrorDotExpr(_, _)
| Self::ErrorTooManyOperations(_) | Self::ErrorTooManyOperations(_)
@ -293,7 +287,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, _) | Self::ErrorVariableNotFound(_, _)
| Self::ErrorModuleNotFound(_, _) | Self::ErrorModuleNotFound(_, _)
| Self::ErrorDataRace(_, _) | Self::ErrorDataRace(_, _)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorAssignmentToConstant(_, _) | Self::ErrorAssignmentToConstant(_, _)
| Self::ErrorMismatchOutputType(_, _, _) | Self::ErrorMismatchOutputType(_, _, _)
| Self::ErrorInExpr(_) | Self::ErrorInExpr(_)
@ -329,7 +322,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, pos) | Self::ErrorVariableNotFound(_, pos)
| Self::ErrorModuleNotFound(_, pos) | Self::ErrorModuleNotFound(_, pos)
| Self::ErrorDataRace(_, pos) | Self::ErrorDataRace(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos) | Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos) | Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos) | Self::ErrorInExpr(pos)
@ -364,7 +356,6 @@ impl EvalAltResult {
| Self::ErrorVariableNotFound(_, pos) | Self::ErrorVariableNotFound(_, pos)
| Self::ErrorModuleNotFound(_, pos) | Self::ErrorModuleNotFound(_, pos)
| Self::ErrorDataRace(_, pos) | Self::ErrorDataRace(_, pos)
| Self::ErrorAssignmentToUnknownLHS(pos)
| Self::ErrorAssignmentToConstant(_, pos) | Self::ErrorAssignmentToConstant(_, pos)
| Self::ErrorMismatchOutputType(_, _, pos) | Self::ErrorMismatchOutputType(_, _, pos)
| Self::ErrorInExpr(pos) | Self::ErrorInExpr(pos)