Skip to main content

melior/ir/type/
tuple.rs

1use super::TypeLike;
2use crate::{ir::Type, Context, Error};
3use mlir_sys::{mlirTupleTypeGet, mlirTupleTypeGetNumTypes, mlirTupleTypeGetType, MlirType};
4
5/// A tuple type.
6#[derive(Clone, Copy, Debug)]
7pub struct TupleType<'c> {
8    r#type: Type<'c>,
9}
10
11impl<'c> TupleType<'c> {
12    /// Creates a tuple type.
13    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    /// Returns a field at a position.
24    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    /// Returns a number of fields.
42    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}