dunge_shade/
op.rs

1use {
2    crate::{
3        eval::{Eval, Expr, GetEntry, Vs},
4        types::{Number, Scalar},
5    },
6    std::{marker::PhantomData, ops},
7};
8
9#[must_use]
10pub struct Ret<A, O> {
11    a: A,
12    t: PhantomData<O>,
13}
14
15impl<A, T> Ret<A, T> {
16    pub(crate) const fn new(a: A) -> Self {
17        Self { a, t: PhantomData }
18    }
19
20    pub(crate) fn inner(self) -> A {
21        self.a
22    }
23}
24
25impl<A, O> Clone for Ret<A, O>
26where
27    A: Clone,
28{
29    #[inline]
30    fn clone(&self) -> Self {
31        Self::new(self.a.clone())
32    }
33}
34
35impl<A, O> Copy for Ret<A, O> where A: Copy {}
36
37type Operand<A, B> = Ret<A, <B as Eval<Vs>>::Out>;
38
39pub struct Unary<A> {
40    a: A,
41    op: Un,
42}
43
44impl<A, O, E> Eval<E> for Ret<Unary<A>, O>
45where
46    A: Eval<E>,
47    E: GetEntry,
48{
49    type Out = O;
50
51    #[inline]
52    fn eval(self, en: &mut E) -> Expr {
53        let Unary { a, op } = self.inner();
54        let x = a.eval(en);
55        en.get_entry().unary(op, x)
56    }
57}
58
59macro_rules! impl_unary {
60    ($o:ident :: $f:ident ( $a:ty ) -> $r:ty) => {
61        impl<A> ops::$o for Operand<A, $a> {
62            type Output = Operand<Unary<Self>, $r>;
63
64            #[inline]
65            fn $f(self) -> Self::Output {
66                Ret::new(Unary {
67                    a: self,
68                    op: Un::$o,
69                })
70            }
71        }
72    };
73}
74
75impl_unary!(Neg::neg(f32) -> f32);
76impl_unary!(Neg::neg(glam::Vec2) -> glam::Vec2);
77impl_unary!(Neg::neg(glam::Vec3) -> glam::Vec3);
78impl_unary!(Neg::neg(glam::Vec4) -> glam::Vec4);
79impl_unary!(Neg::neg(glam::Mat2) -> glam::Mat2);
80impl_unary!(Neg::neg(glam::Mat3) -> glam::Mat3);
81impl_unary!(Neg::neg(glam::Mat4) -> glam::Mat4);
82
83pub struct Binary<A, B> {
84    a: A,
85    b: B,
86    op: Bi,
87}
88
89impl<A, B, O, E> Eval<E> for Ret<Binary<A, B>, O>
90where
91    A: Eval<E>,
92    B: Eval<E>,
93    E: GetEntry,
94{
95    type Out = O;
96
97    #[inline]
98    fn eval(self, en: &mut E) -> Expr {
99        let Binary { a, b, op } = self.inner();
100        let x = a.eval(en);
101        let y = b.eval(en);
102        en.get_entry().binary(op, x, y)
103    }
104}
105
106macro_rules! impl_binary {
107    ($o:ident :: $f:ident ( $a:ty, $b:ty ) -> $r:ty) => {
108        impl<A> ops::$o<Operand<A, $b>> for $a {
109            type Output = Operand<Binary<Self, Operand<A, $b>>, $r>;
110
111            #[inline]
112            fn $f(self, b: Operand<A, $b>) -> Self::Output {
113                Ret::new(Binary {
114                    a: self,
115                    b,
116                    op: Bi::$o,
117                })
118            }
119        }
120
121        impl<A> ops::$o<$a> for Operand<A, $b> {
122            type Output = Operand<Binary<Self, $a>, $r>;
123
124            #[inline]
125            fn $f(self, b: $a) -> Self::Output {
126                Ret::new(Binary {
127                    a: self,
128                    b,
129                    op: Bi::$o,
130                })
131            }
132        }
133
134        impl<A, B> ops::$o<Operand<B, $b>> for Operand<A, $a> {
135            type Output = Operand<Binary<Self, Operand<B, $b>>, $r>;
136
137            #[inline]
138            fn $f(self, b: Operand<B, $b>) -> Self::Output {
139                Ret::new(Binary {
140                    a: self,
141                    b,
142                    op: Bi::$o,
143                })
144            }
145        }
146    };
147}
148
149impl_binary!(Add::add(f32, f32) -> f32);
150impl_binary!(Sub::sub(f32, f32) -> f32);
151impl_binary!(Mul::mul(f32, f32) -> f32);
152impl_binary!(Div::div(f32, f32) -> f32);
153impl_binary!(Rem::rem(f32, f32) -> f32);
154impl_binary!(Add::add(i32, i32) -> i32);
155impl_binary!(Sub::sub(i32, i32) -> i32);
156impl_binary!(Mul::mul(i32, i32) -> i32);
157impl_binary!(Div::div(i32, i32) -> i32);
158impl_binary!(Rem::rem(i32, i32) -> i32);
159impl_binary!(Add::add(u32, u32) -> u32);
160impl_binary!(Sub::sub(u32, u32) -> u32);
161impl_binary!(Mul::mul(u32, u32) -> u32);
162impl_binary!(Div::div(u32, u32) -> u32);
163impl_binary!(Rem::rem(u32, u32) -> u32);
164impl_binary!(Shl::shl(u32, u32) -> u32);
165impl_binary!(Shr::shr(u32, u32) -> u32);
166impl_binary!(BitAnd::bitand(u32, u32) -> u32);
167impl_binary!(BitOr::bitor(u32, u32) -> u32);
168impl_binary!(BitXor::bitxor(u32, u32) -> u32);
169
170impl_binary!(Add::add(glam::Vec2, glam::Vec2) -> glam::Vec2);
171impl_binary!(Add::add(glam::Vec3, glam::Vec3) -> glam::Vec3);
172impl_binary!(Add::add(glam::Vec4, glam::Vec4) -> glam::Vec4);
173impl_binary!(Sub::sub(glam::Vec2, glam::Vec2) -> glam::Vec2);
174impl_binary!(Sub::sub(glam::Vec3, glam::Vec3) -> glam::Vec3);
175impl_binary!(Sub::sub(glam::Vec4, glam::Vec4) -> glam::Vec4);
176impl_binary!(Mul::mul(glam::Vec2, glam::Vec2) -> glam::Vec2);
177impl_binary!(Mul::mul(glam::Vec3, glam::Vec3) -> glam::Vec3);
178impl_binary!(Mul::mul(glam::Vec4, glam::Vec4) -> glam::Vec4);
179
180impl_binary!(Mul::mul(f32, glam::Vec2) -> glam::Vec2);
181impl_binary!(Mul::mul(glam::Vec2, f32) -> glam::Vec2);
182impl_binary!(Mul::mul(f32, glam::Vec3) -> glam::Vec3);
183impl_binary!(Mul::mul(glam::Vec3, f32) -> glam::Vec3);
184impl_binary!(Mul::mul(f32, glam::Vec4) -> glam::Vec4);
185impl_binary!(Mul::mul(glam::Vec4, f32) -> glam::Vec4);
186
187impl_binary!(Add::add(glam::Mat2, glam::Mat2) -> glam::Mat2);
188impl_binary!(Add::add(glam::Mat3, glam::Mat3) -> glam::Mat3);
189impl_binary!(Add::add(glam::Mat4, glam::Mat4) -> glam::Mat4);
190impl_binary!(Sub::sub(glam::Mat2, glam::Mat2) -> glam::Mat2);
191impl_binary!(Sub::sub(glam::Mat3, glam::Mat3) -> glam::Mat3);
192impl_binary!(Sub::sub(glam::Mat4, glam::Mat4) -> glam::Mat4);
193impl_binary!(Mul::mul(glam::Mat2, glam::Mat2) -> glam::Mat2);
194impl_binary!(Mul::mul(glam::Mat3, glam::Mat3) -> glam::Mat3);
195impl_binary!(Mul::mul(glam::Mat4, glam::Mat4) -> glam::Mat4);
196impl_binary!(Mul::mul(f32, glam::Mat2) -> glam::Mat2);
197impl_binary!(Mul::mul(f32, glam::Mat3) -> glam::Mat3);
198impl_binary!(Mul::mul(f32, glam::Mat4) -> glam::Mat4);
199impl_binary!(Mul::mul(glam::Mat2, glam::Vec2) -> glam::Vec2);
200impl_binary!(Mul::mul(glam::Mat3, glam::Vec3) -> glam::Vec3);
201impl_binary!(Mul::mul(glam::Mat4, glam::Vec4) -> glam::Vec4);
202
203pub const fn not<A, B, E>(a: A) -> Ret<Unary<A>, bool>
204where
205    A: Eval<E, Out = bool>,
206{
207    Ret::new(Unary { a, op: Un::Not })
208}
209
210pub const fn and<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
211where
212    A: Eval<E, Out = bool>,
213    B: Eval<E, Out = bool>,
214{
215    Ret::new(Binary { a, b, op: Bi::And })
216}
217
218pub const fn or<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
219where
220    A: Eval<E, Out = bool>,
221    B: Eval<E, Out = bool>,
222{
223    Ret::new(Binary { a, b, op: Bi::Or })
224}
225
226pub const fn eq<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
227where
228    A: Eval<E, Out: Scalar>,
229    B: Eval<E, Out = A::Out>,
230{
231    Ret::new(Binary { a, b, op: Bi::Eq })
232}
233
234pub const fn ne<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
235where
236    A: Eval<E, Out: Scalar>,
237    B: Eval<E, Out = A::Out>,
238{
239    Ret::new(Binary { a, b, op: Bi::Ne })
240}
241
242pub const fn lt<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
243where
244    A: Eval<E, Out: Number>,
245    B: Eval<E, Out = A::Out>,
246{
247    Ret::new(Binary { a, b, op: Bi::Lt })
248}
249
250pub const fn le<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
251where
252    A: Eval<E, Out: Number>,
253    B: Eval<E, Out = A::Out>,
254{
255    Ret::new(Binary { a, b, op: Bi::Le })
256}
257
258pub const fn gt<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
259where
260    A: Eval<E, Out: Number>,
261    B: Eval<E, Out = A::Out>,
262{
263    Ret::new(Binary { a, b, op: Bi::Gt })
264}
265
266pub const fn ge<A, B, E>(a: A, b: B) -> Ret<Binary<A, B>, bool>
267where
268    A: Eval<E, Out: Number>,
269    B: Eval<E, Out = A::Out>,
270{
271    Ret::new(Binary { a, b, op: Bi::Ge })
272}
273
274pub(crate) enum Un {
275    Neg,
276    Not,
277}
278
279impl Un {
280    pub(crate) fn operator(self) -> naga::UnaryOperator {
281        match self {
282            Self::Neg => naga::UnaryOperator::Negate,
283            Self::Not => naga::UnaryOperator::LogicalNot,
284        }
285    }
286}
287
288pub(crate) enum Bi {
289    Add,
290    Sub,
291    Mul,
292    Div,
293    Rem,
294    Shl,
295    Shr,
296    And,
297    Or,
298    BitAnd,
299    BitOr,
300    BitXor,
301    Eq,
302    Ne,
303    Lt,
304    Le,
305    Gt,
306    Ge,
307}
308
309impl Bi {
310    pub(crate) fn operator(self) -> naga::BinaryOperator {
311        match self {
312            Self::Add => naga::BinaryOperator::Add,
313            Self::Sub => naga::BinaryOperator::Subtract,
314            Self::Mul => naga::BinaryOperator::Multiply,
315            Self::Div => naga::BinaryOperator::Divide,
316            Self::Rem => naga::BinaryOperator::Modulo,
317            Self::Shl => naga::BinaryOperator::ShiftLeft,
318            Self::Shr => naga::BinaryOperator::ShiftRight,
319            Self::And => naga::BinaryOperator::LogicalAnd,
320            Self::Or => naga::BinaryOperator::LogicalOr,
321            Self::BitAnd => naga::BinaryOperator::And,
322            Self::BitOr => naga::BinaryOperator::InclusiveOr,
323            Self::BitXor => naga::BinaryOperator::ExclusiveOr,
324            Self::Eq => naga::BinaryOperator::Equal,
325            Self::Ne => naga::BinaryOperator::NotEqual,
326            Self::Lt => naga::BinaryOperator::Less,
327            Self::Le => naga::BinaryOperator::LessEqual,
328            Self::Gt => naga::BinaryOperator::Greater,
329            Self::Ge => naga::BinaryOperator::GreaterEqual,
330        }
331    }
332}