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}