1use super::TypeLike;
2use crate::{ir::Type, Context, Error};
3use mlir_sys::{mlirTupleTypeGet, mlirTupleTypeGetNumTypes, mlirTupleTypeGetType, MlirType};
4
5#[derive(Clone, Copy, Debug)]
7pub struct TupleType<'c> {
8 r#type: Type<'c>,
9}
10
11impl<'c> TupleType<'c> {
12 pub fn new(context: &'c Context, types: &[Type<'c>]) -> Self {
14 unsafe {
15 Self::from_raw(mlirTupleTypeGet(
16 context.to_raw(),
17 types.len() as isize,
18 types as *const _ as *const _,
19 ))
20 }
21 }
22
23 pub fn r#type(&self, index: usize) -> Result<Type, Error> {
25 if index < self.type_count() {
26 unsafe {
27 Ok(Type::from_raw(mlirTupleTypeGetType(
28 self.r#type.to_raw(),
29 index as isize,
30 )))
31 }
32 } else {
33 Err(Error::PositionOutOfBounds {
34 name: "tuple field",
35 value: self.to_string(),
36 index,
37 })
38 }
39 }
40
41 pub fn type_count(&self) -> usize {
43 unsafe { mlirTupleTypeGetNumTypes(self.r#type.to_raw()) as usize }
44 }
45}
46
47type_traits!(TupleType, is_tuple, "tuple");
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use crate::Context;
53
54 #[test]
55 fn new() {
56 let context = Context::new();
57
58 assert_eq!(
59 Type::from(TupleType::new(&context, &[])),
60 Type::parse(&context, "tuple<>").unwrap()
61 );
62 }
63
64 #[test]
65 fn new_with_field() {
66 let context = Context::new();
67
68 assert_eq!(
69 Type::from(TupleType::new(&context, &[Type::index(&context)])),
70 Type::parse(&context, "tuple<index>").unwrap()
71 );
72 }
73
74 #[test]
75 fn new_with_two_fields() {
76 let context = Context::new();
77 let r#type = Type::index(&context);
78
79 assert_eq!(
80 Type::from(TupleType::new(&context, &[r#type, r#type])),
81 Type::parse(&context, "tuple<index,index>").unwrap()
82 );
83 }
84
85 #[test]
86 fn r#type() {
87 let context = Context::new();
88 let index_type = Type::index(&context);
89 let float64_type = Type::float64(&context);
90 let tuple = TupleType::new(&context, &[index_type, float64_type]);
91
92 assert_eq!(tuple.r#type(0), Ok(index_type));
93 assert_eq!(tuple.r#type(1), Ok(float64_type));
94 }
95
96 #[test]
97 fn type_error() {
98 let context = Context::new();
99 let tuple = TupleType::new(&context, &[]);
100
101 assert_eq!(
102 tuple.r#type(42),
103 Err(Error::PositionOutOfBounds {
104 name: "tuple field",
105 value: tuple.to_string(),
106 index: 42
107 })
108 );
109 }
110
111 #[test]
112 fn type_count() {
113 assert_eq!(TupleType::new(&Context::new(), &[]).type_count(), 0);
114 }
115}