expr/ast/
unary_operator.rs

1use crate::ast::node::Node;
2use crate::Rule;
3use crate::Value::Bool;
4use crate::{bail, Result};
5use crate::{Context, Environment, Value};
6use log::trace;
7use pest::iterators::Pair;
8use std::str::FromStr;
9
10#[derive(Debug, Clone, strum::EnumString)]
11pub enum UnaryOperator {
12    #[strum(serialize = "!")]
13    Not,
14    #[strum(serialize = "+")]
15    Positive,
16    #[strum(serialize = "-")]
17    Negative,
18}
19
20impl From<Pair<'_, Rule>> for UnaryOperator {
21    fn from(pair: Pair<Rule>) -> Self {
22        trace!("[unary_operator] {pair:?}");
23        match pair.as_str() {
24            "not" => UnaryOperator::Not,
25            op => UnaryOperator::from_str(op)
26                .unwrap_or_else(|_| unreachable!("Invalid operator {op}")),
27        }
28    }
29}
30
31impl Environment<'_> {
32    pub fn eval_unary_operator(
33        &self,
34        ctx: &Context,
35        operator: UnaryOperator,
36        node: Node,
37    ) -> Result<Value> {
38        let node = self.eval_expr(ctx, node)?;
39        let result = match operator {
40            UnaryOperator::Not => match node {
41                Bool(b) => Bool(!b),
42                _ => bail!("Invalid operand for operator !"),
43            },
44            UnaryOperator::Positive => match node {
45                Value::Number(n) => Value::Number(n),
46                Value::Float(f) => Value::Float(f),
47                _ => bail!("Invalid operand for operator +"),
48            },
49            UnaryOperator::Negative => match node {
50                Value::Number(n) => Value::Number(-n),
51                Value::Float(f) => Value::Float(-f),
52                _ => bail!("Invalid operand for operator -"),
53            },
54        };
55
56        Ok(result)
57    }
58}