value_expr/
valuer.rs

1use super::data::*;
2
3pub trait Valued<T> {
4    fn to_i32(&self, ctx: &mut T) -> i32;
5}
6pub trait ValuedVec<T> {
7    fn to_i32_one(&self, ctx: &mut T, idx: usize) -> i32;
8    fn to_i32_vec(&self, ctx: &mut T) -> Vec<i32>;
9    fn to_i32_last(&self, ctx: &mut T) -> i32;
10}
11pub trait Context {
12    fn call(&mut self, func: &str, values: &Vec<Value>) -> i32;
13    fn ident_get(&self, ident: &str) -> i32;
14    fn ident_set(&mut self, ident: &str, value: i32);
15    fn call_native(&mut self, _func: &str) -> i32 {
16        unreachable!()
17    }
18}
19macro_rules! i2b {
20    ($expr:expr) => {
21        $expr != 0
22    };
23}
24macro_rules! b2i {
25    ($expr:expr) => {
26        if $expr {
27            1
28        } else {
29            0
30        }
31    };
32}
33impl UnOp {
34    pub fn to_i32<T: Context, V: Valued<T>>(&self, ctx: &mut T, value: V) -> i32 {
35        match self {
36            UnOp::Not => b2i!(!i2b!(value.to_i32(ctx))),
37            UnOp::Neg => -value.to_i32(ctx),
38        }
39    }
40}
41
42impl BinOp {
43    pub fn to_i32<T: Context, V: Valued<T>>(&self, ctx: &mut T, left: V, right: V) -> i32 {
44        match self {
45            BinOp::Add => left.to_i32(ctx) + right.to_i32(ctx),
46            BinOp::Sub => left.to_i32(ctx) - right.to_i32(ctx),
47            BinOp::Mul => left.to_i32(ctx) * right.to_i32(ctx),
48            BinOp::Div => left.to_i32(ctx) / right.to_i32(ctx),
49            BinOp::Rem => left.to_i32(ctx) % right.to_i32(ctx),
50            BinOp::BitXor => left.to_i32(ctx) ^ right.to_i32(ctx),
51            BinOp::BitAnd => left.to_i32(ctx) & right.to_i32(ctx),
52            BinOp::BitOr => left.to_i32(ctx) | right.to_i32(ctx),
53            BinOp::Shl => left.to_i32(ctx) << right.to_i32(ctx),
54            BinOp::Shr => left.to_i32(ctx) >> right.to_i32(ctx),
55            BinOp::And => b2i!(i2b!(left.to_i32(ctx)) && i2b!(right.to_i32(ctx))),
56            BinOp::Or => b2i!(i2b!(left.to_i32(ctx)) || i2b!(right.to_i32(ctx))),
57            BinOp::Eq => b2i!(left.to_i32(ctx) == right.to_i32(ctx)),
58            BinOp::Lt => b2i!(left.to_i32(ctx) < right.to_i32(ctx)),
59            BinOp::Le => b2i!(left.to_i32(ctx) <= right.to_i32(ctx)),
60            BinOp::Ne => b2i!(left.to_i32(ctx) != right.to_i32(ctx)),
61            BinOp::Ge => b2i!(left.to_i32(ctx) >= right.to_i32(ctx)),
62            BinOp::Gt => b2i!(left.to_i32(ctx) > right.to_i32(ctx)),
63        }
64    }
65}
66
67impl AssignOp {
68    pub fn to_i32<T: Context, V: Valued<T>>(&self, ctx: &mut T, ident: &str, value: V) -> i32 {
69        let v = match self {
70            AssignOp::Assign => value.to_i32(ctx),
71            AssignOp::AddAssign => ctx.ident_get(ident) + value.to_i32(ctx),
72            AssignOp::SubAssign => ctx.ident_get(ident) - value.to_i32(ctx),
73            AssignOp::MulAssign => ctx.ident_get(ident) * value.to_i32(ctx),
74            AssignOp::DivAssign => ctx.ident_get(ident) / value.to_i32(ctx),
75            AssignOp::RemAssign => ctx.ident_get(ident) % value.to_i32(ctx),
76            AssignOp::BitXorAssign => ctx.ident_get(ident) ^ value.to_i32(ctx),
77            AssignOp::BitAndAssign => ctx.ident_get(ident) & value.to_i32(ctx),
78            AssignOp::BitOrAssign => ctx.ident_get(ident) | value.to_i32(ctx),
79            AssignOp::ShlAssign => ctx.ident_get(ident) << value.to_i32(ctx),
80            AssignOp::ShrAssign => ctx.ident_get(ident) >> value.to_i32(ctx),
81        };
82        ctx.ident_set(ident, v);
83        v
84    }
85}
86
87impl<T: Context> Valued<T> for Value {
88    fn to_i32(&self, ctx: &mut T) -> i32 {
89        match self {
90            Value::Integer(v) => *v,
91            Value::Unary(op, v) => op.to_i32(ctx, v),
92            Value::Binary(op, l, r) => op.to_i32(ctx, l, r),
93            Value::Paren(v) => v.to_i32_last(ctx),
94            Value::FuncLike(v, args) => ctx.call(v, args),
95            Value::Ident(ident) => ctx.ident_get(ident),
96            Value::Assign(op, ident, v) => op.to_i32(ctx, ident, v),
97            Value::Native(v) => ctx.call_native(v),
98        }
99    }
100}
101impl<T: Context> Valued<T> for &Box<Value> {
102    fn to_i32(&self, ctx: &mut T) -> i32 {
103        self.as_ref().to_i32(ctx)
104    }
105}
106impl<T: Context> ValuedVec<T> for [Value] {
107    fn to_i32_one(&self, ctx: &mut T, idx: usize) -> i32 {
108        self.get(idx).map(|e| e.to_i32(ctx)).unwrap_or_default()
109    }
110    fn to_i32_vec(&self, ctx: &mut T) -> Vec<i32> {
111        self.iter().map(|e| e.to_i32(ctx)).collect()
112    }
113    fn to_i32_last(&self, ctx: &mut T) -> i32 {
114        self.iter()
115            .map(|e| e.to_i32(ctx))
116            .last()
117            .unwrap_or_default()
118    }
119}
120
121pub(crate) use {b2i, i2b};