use super::{Expr, ExprEvaluator};
use crate::err::*;
use crate::eval::*;
use crate::value::*;
#[derive(Debug, Clone)]
pub struct UnaryOpExpr {
pub op: UnaryOperator,
pub expr: Index,
}
impl Expr for UnaryOpExpr {
fn resolve(
&self,
_index: Index,
evaluation: &mut dyn ExprEvaluator,
) -> Result<ValueOrReference, ErrorKind> {
evaluation.ensure_resolved(vec![self.expr])?;
let value = evaluation.get_value(self.expr)?;
Ok(self.op.apply(value)?.into())
}
}
#[derive(Debug, Copy, Clone)]
pub enum UnaryOperator {
Neg,
Not,
}
impl UnaryOperator {
pub fn symbol(self) -> &'static str {
match self {
UnaryOperator::Neg => "-",
UnaryOperator::Not => "!",
}
}
pub fn apply(self, value: Value) -> Result<Value, ErrorKind> {
match self {
UnaryOperator::Neg => match &value {
Value::Integer(v) => Ok(Value::Integer(-v)),
Value::Decimal(v) => Ok(Value::Decimal(-v)),
_ => Err(ErrorKind::UnaryOpTypeNotAllowed {
op: self,
kind: value.kind(),
}),
},
UnaryOperator::Not => match &value {
Value::Boolean(v) => Ok(Value::Boolean(!v)),
_ => Err(ErrorKind::UnaryOpTypeNotAllowed {
op: self,
kind: value.kind(),
}),
},
}
}
}