cco 0.2.0

cascading configuration
Documentation
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(),
                }),
            },
        }
    }
}