Implement add-assign and subtract-assign
This commit is contained in:
parent
f70c8f2b40
commit
ec9f17070c
@ -62,7 +62,33 @@ impl<'src> AbstractTree for Assignment<'src> {
|
|||||||
r#break => return Ok(r#break),
|
r#break => return Ok(r#break),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match self.operator {
|
||||||
|
AssignmentOperator::Assign => {
|
||||||
context.set_value(self.identifier, value)?;
|
context.set_value(self.identifier, value)?;
|
||||||
|
}
|
||||||
|
AssignmentOperator::AddAssign => {
|
||||||
|
if let Some(previous_value) = context.get_value(&self.identifier)? {
|
||||||
|
let new_value = previous_value.add(&value)?;
|
||||||
|
|
||||||
|
context.set_value(self.identifier, new_value)?;
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::VariableNotFound(self.identifier),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AssignmentOperator::SubAssign => {
|
||||||
|
if let Some(previous_value) = context.get_value(&self.identifier)? {
|
||||||
|
let new_value = previous_value.subtract(&value)?;
|
||||||
|
|
||||||
|
context.set_value(self.identifier, new_value)?;
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::VariableNotFound(self.identifier),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
@ -97,6 +123,52 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_assign_value() {
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_value(Identifier::new("foobar"), Value::integer(1))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Assignment::new(
|
||||||
|
Identifier::new("foobar"),
|
||||||
|
None,
|
||||||
|
AssignmentOperator::AddAssign,
|
||||||
|
Statement::Expression(Expression::Value(ValueNode::Integer(41))),
|
||||||
|
)
|
||||||
|
.run(&context)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
context.get_value(&Identifier::new("foobar")),
|
||||||
|
Ok(Some(Value::integer(42)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn subtract_assign_value() {
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_value(Identifier::new("foobar"), Value::integer(43))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Assignment::new(
|
||||||
|
Identifier::new("foobar"),
|
||||||
|
None,
|
||||||
|
AssignmentOperator::SubAssign,
|
||||||
|
Statement::Expression(Expression::Value(ValueNode::Integer(1))),
|
||||||
|
)
|
||||||
|
.run(&context)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
context.get_value(&Identifier::new("foobar")),
|
||||||
|
Ok(Some(Value::integer(42)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn type_check() {
|
fn type_check() {
|
||||||
let validation = Assignment::new(
|
let validation = Assignment::new(
|
||||||
|
@ -54,29 +54,13 @@ impl<'src> AbstractTree for Math<'src> {
|
|||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
left_value.add(&right_value)?
|
||||||
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
|
||||||
{
|
|
||||||
Value::integer(left + right)
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedIntegerOrFloat,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Math::Subtract(left, right) => {
|
Math::Subtract(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
left_value.subtract(&right_value)?
|
||||||
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
|
||||||
{
|
|
||||||
Value::integer(left - right)
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::ExpectedIntegerOrFloat,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Math::Multiply(left, right) => {
|
Math::Multiply(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.run(_context)?.as_return_value()?;
|
||||||
|
20
src/value.rs
20
src/value.rs
@ -128,6 +128,26 @@ impl Value {
|
|||||||
pub fn is_none(&self) -> bool {
|
pub fn is_none(&self) -> bool {
|
||||||
self == get_none()
|
self == get_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add(&self, other: &Self) -> Result<Value, ValidationError> {
|
||||||
|
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||||
|
(self.inner().as_ref(), other.inner().as_ref())
|
||||||
|
{
|
||||||
|
Ok(Value::integer(left + right))
|
||||||
|
} else {
|
||||||
|
Err(ValidationError::ExpectedIntegerOrFloat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subtract(&self, other: &Self) -> Result<Value, ValidationError> {
|
||||||
|
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||||
|
(self.inner().as_ref(), other.inner().as_ref())
|
||||||
|
{
|
||||||
|
Ok(Value::integer(left - right))
|
||||||
|
} else {
|
||||||
|
Err(ValidationError::ExpectedIntegerOrFloat)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
|
Loading…
Reference in New Issue
Block a user