expr/ast/
unary_operator.rs1use 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}