1use crate::{
4 Error,
5 conv::{Convert, convert_ty},
6 syntax::{AddressSpace, BinaryOperator, UnaryOperator},
7 ty::{Ty, Type},
8};
9
10type E = Error;
11
12pub fn type_unary_op(operator: UnaryOperator, operand: &Type) -> Result<Type, E> {
14 match operator {
15 UnaryOperator::LogicalNegation => operand.op_not(),
16 UnaryOperator::Negation => operand.op_neg(),
17 UnaryOperator::BitwiseComplement => operand.op_bitnot(),
18 UnaryOperator::AddressOf => operand.op_ref(),
19 UnaryOperator::Indirection => operand.op_deref(),
20 }
21}
22
23pub fn type_binary_op(op: BinaryOperator, lhs: &Type, rhs: &Type) -> Result<Type, E> {
25 match op {
26 BinaryOperator::ShortCircuitOr => lhs.op_or(rhs),
27 BinaryOperator::ShortCircuitAnd => lhs.op_and(rhs),
28 BinaryOperator::Addition => lhs.op_add(rhs),
29 BinaryOperator::Subtraction => lhs.op_sub(rhs),
30 BinaryOperator::Multiplication => lhs.op_mul(rhs),
31 BinaryOperator::Division => lhs.op_div(rhs),
32 BinaryOperator::Remainder => lhs.op_rem(rhs),
33 BinaryOperator::Equality => lhs.op_eq(rhs),
34 BinaryOperator::Inequality => lhs.op_ne(rhs),
35 BinaryOperator::LessThan => lhs.op_lt(rhs),
36 BinaryOperator::LessThanEqual => lhs.op_le(rhs),
37 BinaryOperator::GreaterThan => lhs.op_gt(rhs),
38 BinaryOperator::GreaterThanEqual => lhs.op_ge(rhs),
39 BinaryOperator::BitwiseOr => lhs.op_bitor(rhs),
40 BinaryOperator::BitwiseAnd => lhs.op_bitand(rhs),
41 BinaryOperator::BitwiseXor => lhs.op_bitxor(rhs),
42 BinaryOperator::ShiftLeft => lhs.op_shl(rhs),
43 BinaryOperator::ShiftRight => lhs.op_shr(rhs),
44 }
45}
46
47impl Type {
53 pub fn op_not(&self) -> Result<Self, E> {
54 match self {
55 Self::Bool | Self::Vec(_, _) => Ok(self.clone()),
56 _ => Err(E::Unary(UnaryOperator::LogicalNegation, self.clone())),
57 }
58 }
59 pub fn op_or(&self, rhs: &Type) -> Result<Self, E> {
60 match (self, rhs) {
61 (Type::Bool, Type::Bool) => Ok(Type::Bool),
62 _ => Err(E::Binary(
63 BinaryOperator::ShortCircuitOr,
64 self.ty(),
65 rhs.ty(),
66 )),
67 }
68 }
69 pub fn op_and(&self, rhs: &Type) -> Result<Self, E> {
70 match (self, rhs) {
71 (Type::Bool, Type::Bool) => Ok(Type::Bool),
72 _ => Err(E::Binary(
73 BinaryOperator::ShortCircuitAnd,
74 self.ty(),
75 rhs.ty(),
76 )),
77 }
78 }
79}
80
81impl Type {
87 pub fn op_neg(&self) -> Result<Self, E> {
90 if self.is_scalar() || matches!(self, Type::Vec(_, inner_ty) if inner_ty.is_scalar()) {
91 Ok(self.clone())
92 } else {
93 Err(E::Unary(UnaryOperator::Negation, self.ty()))
94 }
95 }
96
97 pub fn op_add(&self, rhs: &Type) -> Result<Self, E> {
102 let err = || E::Binary(BinaryOperator::Addition, self.ty(), rhs.ty());
103 match (self, rhs) {
104 (lhs, rhs) if lhs.is_scalar() && rhs.is_scalar() || lhs.is_vec() && rhs.is_vec() => {
105 let ty = convert_ty(self, rhs).ok_or_else(err)?;
106 Ok(ty.clone())
107 }
108 (scalar_ty, Type::Vec(n, vec_ty)) | (Type::Vec(n, vec_ty), scalar_ty)
109 if scalar_ty.is_scalar() =>
110 {
111 let inner_ty = convert_ty(scalar_ty, vec_ty).ok_or_else(err)?;
112 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
113 }
114 (Type::Mat(c1, r1, lhs), Type::Mat(c2, r2, rhs)) if c1 == c2 && r1 == r2 => {
115 let inner_ty = convert_ty(lhs, rhs).ok_or_else(err)?;
116 Ok(Type::Mat(*c1, *c2, Box::new(inner_ty.clone())))
117 }
118 _ => Err(err()),
119 }
120 }
121
122 pub fn op_sub(&self, rhs: &Type) -> Result<Self, E> {
127 let err = || E::Binary(BinaryOperator::Subtraction, self.ty(), rhs.ty());
128 match (self, rhs) {
129 (lhs, rhs) if lhs.is_scalar() && rhs.is_scalar() || lhs.is_vec() && rhs.is_vec() => {
130 let ty = convert_ty(self, rhs).ok_or_else(err)?;
131 Ok(ty.clone())
132 }
133 (scalar_ty, Type::Vec(n, vec_ty)) | (Type::Vec(n, vec_ty), scalar_ty)
134 if scalar_ty.is_scalar() =>
135 {
136 let inner_ty = convert_ty(scalar_ty, vec_ty).ok_or_else(err)?;
137 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
138 }
139 (Type::Mat(c1, r1, lhs), Type::Mat(c2, r2, rhs)) if c1 == c2 && r1 == r2 => {
140 let inner_ty = convert_ty(lhs, rhs).ok_or_else(err)?;
141 Ok(Type::Mat(*c1, *c2, Box::new(inner_ty.clone())))
142 }
143 _ => Err(err()),
144 }
145 }
146
147 pub fn op_mul(&self, rhs: &Type) -> Result<Self, E> {
154 let err = || E::Binary(BinaryOperator::Multiplication, self.ty(), rhs.ty());
155 match (self, rhs) {
156 (lhs, rhs) if lhs.is_scalar() && rhs.is_scalar() || lhs.is_vec() && rhs.is_vec() => {
157 let ty = convert_ty(self, rhs).ok_or_else(err)?;
158 Ok(ty.clone())
159 }
160 (scalar_ty, Type::Vec(n, vec_ty)) | (Type::Vec(n, vec_ty), scalar_ty)
162 if scalar_ty.is_scalar() =>
163 {
164 let inner_ty = convert_ty(scalar_ty, vec_ty).ok_or_else(err)?;
165 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
166 }
167 (scalar_ty, Type::Mat(c, r, mat_ty)) | (Type::Mat(c, r, mat_ty), scalar_ty)
169 if scalar_ty.is_scalar() =>
170 {
171 let inner_ty = convert_ty(scalar_ty, mat_ty).ok_or_else(err)?;
172 Ok(Type::Mat(*c, *r, Box::new(inner_ty.clone())))
173 }
174 (Type::Vec(n1, vec_ty), Type::Mat(n, n2, mat_ty))
176 | (Type::Mat(n1, n, mat_ty), Type::Vec(n2, vec_ty))
178 if n1 == n2 => {
179 let inner_ty = convert_ty(vec_ty, mat_ty).ok_or_else(err)?;
180 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
181 }
182 (Type::Mat(k1, r, lhs), Type::Mat(c, k2, rhs)) if k1 == k2 => {
184 let inner_ty = convert_ty(lhs, rhs).ok_or_else(err)?;
185 Ok(Type::Mat(*c, *r, Box::new(inner_ty.clone())))
186 }
187 _ => Err(err()),
188 }
189 }
190
191 pub fn op_div(&self, rhs: &Type) -> Result<Self, E> {
195 let err = || E::Binary(BinaryOperator::Division, self.ty(), rhs.ty());
196 match (self, rhs) {
197 (lhs, rhs) if lhs.is_scalar() && rhs.is_scalar() || lhs.is_vec() && rhs.is_vec() => {
198 let ty = convert_ty(self, rhs).ok_or_else(err)?;
199 Ok(ty.clone())
200 }
201 (scalar_ty, Type::Vec(n, vec_ty)) | (Type::Vec(n, vec_ty), scalar_ty)
202 if scalar_ty.is_scalar() =>
203 {
204 let inner_ty = convert_ty(scalar_ty, vec_ty).ok_or_else(err)?;
205 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
206 }
207 _ => Err(err()),
208 }
209 }
210
211 pub fn op_rem(&self, rhs: &Type) -> Result<Self, E> {
215 let err = || E::Binary(BinaryOperator::Remainder, self.ty(), rhs.ty());
216 match (self, rhs) {
217 (lhs, rhs) if lhs.is_scalar() && rhs.is_scalar() || lhs.is_vec() && rhs.is_vec() => {
218 let ty = convert_ty(self, rhs).ok_or_else(err)?;
219 Ok(ty.clone())
220 }
221 (scalar_ty, Type::Vec(n, vec_ty)) | (Type::Vec(n, vec_ty), scalar_ty)
222 if scalar_ty.is_scalar() =>
223 {
224 let inner_ty = convert_ty(scalar_ty, vec_ty).ok_or_else(err)?;
225 Ok(Type::Vec(*n, Box::new(inner_ty.clone())))
226 }
227 _ => Err(err()),
228 }
229 }
230}
231
232impl Type {
238 pub fn op_eq(&self, rhs: &Type) -> Result<Type, E> {
241 let err = || E::Binary(BinaryOperator::Equality, self.ty(), rhs.ty());
242 match convert_ty(self, rhs).ok_or_else(err)? {
243 ty if ty.is_scalar() => Ok(Type::Bool),
244 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
245 _ => Err(err()),
246 }
247 }
248 pub fn op_ne(&self, rhs: &Type) -> Result<Type, E> {
251 let err = || E::Binary(BinaryOperator::Inequality, self.ty(), rhs.ty());
252 match convert_ty(self, rhs).ok_or_else(err)? {
253 ty if ty.is_scalar() => Ok(Type::Bool),
254 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
255 _ => Err(err()),
256 }
257 }
258 pub fn op_lt(&self, rhs: &Type) -> Result<Type, E> {
261 let err = || E::Binary(BinaryOperator::LessThan, self.ty(), rhs.ty());
262 match convert_ty(self, rhs).ok_or_else(err)? {
263 ty if ty.is_scalar() => Ok(Type::Bool),
264 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
265 _ => Err(err()),
266 }
267 }
268 pub fn op_le(&self, rhs: &Type) -> Result<Type, E> {
271 let err = || E::Binary(BinaryOperator::LessThanEqual, self.ty(), rhs.ty());
272 match convert_ty(self, rhs).ok_or_else(err)? {
273 ty if ty.is_scalar() => Ok(Type::Bool),
274 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
275 _ => Err(err()),
276 }
277 }
278 pub fn op_gt(&self, rhs: &Type) -> Result<Type, E> {
281 let err = || E::Binary(BinaryOperator::GreaterThan, self.ty(), rhs.ty());
282 match convert_ty(self, rhs).ok_or_else(err)? {
283 ty if ty.is_scalar() => Ok(Type::Bool),
284 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
285 _ => Err(err()),
286 }
287 }
288 pub fn op_ge(&self, rhs: &Type) -> Result<Type, E> {
291 let err = || E::Binary(BinaryOperator::GreaterThanEqual, self.ty(), rhs.ty());
292 match convert_ty(self, rhs).ok_or_else(err)? {
293 ty if ty.is_scalar() => Ok(Type::Bool),
294 Type::Vec(n, _) => Ok(Type::Vec(*n, Box::new(Type::Bool))),
295 _ => Err(err()),
296 }
297 }
298}
299
300impl Type {
306 pub fn op_bitnot(&self) -> Result<Type, E> {
309 match self {
310 ty if ty.is_integer() => Ok(self.clone()),
311 Type::Vec(_, ty) if ty.is_integer() => Ok(self.clone()),
312 _ => Err(E::Unary(UnaryOperator::BitwiseComplement, self.ty())),
313 }
314 }
315
316 pub fn op_bitor(&self, rhs: &Type) -> Result<Type, E> {
322 let err = || E::Binary(BinaryOperator::BitwiseOr, self.ty(), rhs.ty());
323 match convert_ty(self, rhs).ok_or_else(err)? {
324 ty if ty.is_integer() => Ok(self.clone()),
325 Type::Vec(_, ty) if ty.is_integer() => Ok(self.clone()),
326 Type::Vec(_, ty) if ty.is_bool() => Ok(self.clone()),
327 _ => Err(err()),
328 }
329 }
330
331 pub fn op_bitand(&self, rhs: &Type) -> Result<Type, E> {
337 let err = || E::Binary(BinaryOperator::BitwiseAnd, self.ty(), rhs.ty());
338 match convert_ty(self, rhs).ok_or_else(err)? {
339 ty if ty.is_integer() => Ok(self.clone()),
340 Type::Vec(_, ty) if ty.is_integer() => Ok(self.clone()),
341 Type::Vec(_, ty) if ty.is_bool() => Ok(self.clone()),
342 _ => Err(err()),
343 }
344 }
345
346 pub fn op_bitxor(&self, rhs: &Type) -> Result<Type, E> {
349 let err = || E::Binary(BinaryOperator::BitwiseXor, self.ty(), rhs.ty());
350 match convert_ty(self, rhs).ok_or_else(err)? {
351 ty if ty.is_integer() => Ok(self.clone()),
352 Type::Vec(_, ty) if ty.is_integer() => Ok(self.clone()),
353 _ => Err(err()),
354 }
355 }
356
357 pub fn op_shl(&self, rhs: &Type) -> Result<Type, E> {
361 let err = || E::Binary(BinaryOperator::ShiftLeft, self.ty(), rhs.ty());
362 let rhs = rhs.convert_inner_to(&Type::U32).ok_or_else(err)?;
363 match (self, rhs) {
364 (lhs, Type::U32) if lhs.is_integer() => Ok(lhs.clone()),
365 (lhs, Type::Vec(_, _)) => Ok(lhs.clone()),
366 _ => Err(err()),
367 }
368 }
369
370 pub fn op_shr(&self, rhs: &Type) -> Result<Type, E> {
374 let err = || E::Binary(BinaryOperator::ShiftRight, self.ty(), rhs.ty());
375 let rhs = rhs.convert_inner_to(&Type::U32).ok_or_else(err)?;
376 match (self, rhs) {
377 (lhs, Type::U32) if lhs.is_integer() => Ok(lhs.clone()),
378 (lhs, Type::Vec(_, _)) => Ok(lhs.clone()),
379 _ => Err(err()),
380 }
381 }
382}
383
384impl Type {
391 pub fn op_ref(&self) -> Result<Type, E> {
392 match self {
393 Type::Ref(a_s, ty, a_m) => {
394 if *a_s == AddressSpace::Handle {
395 Err(E::PtrHandle)
397 } else if false {
398 Err(E::PtrVecComp)
401 } else {
402 Ok(Type::Ptr(*a_s, ty.clone(), *a_m))
403 }
404 }
405 _ => Err(E::Unary(UnaryOperator::AddressOf, self.ty())),
406 }
407 }
408
409 pub fn op_deref(&self) -> Result<Type, E> {
410 match self {
411 Type::Ptr(a_s, ty, a_m) => Ok(Type::Ref(*a_s, ty.clone(), *a_m)),
412 _ => Err(E::Unary(UnaryOperator::Indirection, self.ty())),
413 }
414 }
415}