1use super::{Block, BlockRef};
2use mlir_sys::{
3 mlirRegionAppendOwnedBlock, mlirRegionCreate, mlirRegionDestroy, mlirRegionEqual,
4 mlirRegionGetFirstBlock, mlirRegionInsertOwnedBlockAfter, mlirRegionInsertOwnedBlockBefore,
5 MlirRegion,
6};
7use std::{
8 marker::PhantomData,
9 mem::{forget, transmute},
10 ops::Deref,
11};
12
13#[derive(Debug)]
15pub struct Region<'c> {
16 raw: MlirRegion,
17 _block: PhantomData<Block<'c>>,
18}
19
20impl<'c> Region<'c> {
21 pub fn new() -> Self {
23 Self {
24 raw: unsafe { mlirRegionCreate() },
25 _block: Default::default(),
26 }
27 }
28
29 pub fn first_block(&self) -> Option<BlockRef<'c, '_>> {
31 unsafe {
32 let block = mlirRegionGetFirstBlock(self.raw);
33
34 if block.ptr.is_null() {
35 None
36 } else {
37 Some(BlockRef::from_raw(block))
38 }
39 }
40 }
41
42 pub fn insert_block_after(&self, one: BlockRef<'c, '_>, other: Block<'c>) -> BlockRef<'c, '_> {
44 unsafe {
45 let r#ref = BlockRef::from_raw(other.to_raw());
46
47 mlirRegionInsertOwnedBlockAfter(self.raw, one.to_raw(), other.into_raw());
48
49 r#ref
50 }
51 }
52
53 pub fn insert_block_before(&self, one: BlockRef<'c, '_>, other: Block<'c>) -> BlockRef<'c, '_> {
55 unsafe {
56 let r#ref = BlockRef::from_raw(other.to_raw());
57
58 mlirRegionInsertOwnedBlockBefore(self.raw, one.to_raw(), other.into_raw());
59
60 r#ref
61 }
62 }
63
64 pub fn append_block(&self, block: Block<'c>) -> BlockRef<'c, '_> {
66 unsafe {
67 let r#ref = BlockRef::from_raw(block.to_raw());
68
69 mlirRegionAppendOwnedBlock(self.raw, block.into_raw());
70
71 r#ref
72 }
73 }
74
75 pub const fn into_raw(self) -> mlir_sys::MlirRegion {
77 let region = self.raw;
78
79 forget(self);
80
81 region
82 }
83}
84
85impl Default for Region<'_> {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl Drop for Region<'_> {
92 fn drop(&mut self) {
93 unsafe { mlirRegionDestroy(self.raw) }
94 }
95}
96
97impl PartialEq for Region<'_> {
98 fn eq(&self, other: &Self) -> bool {
99 unsafe { mlirRegionEqual(self.raw, other.raw) }
100 }
101}
102
103impl Eq for Region<'_> {}
104
105#[derive(Clone, Copy, Debug)]
107pub struct RegionRef<'c, 'a> {
108 raw: MlirRegion,
109 _region: PhantomData<&'a Region<'c>>,
110}
111
112impl RegionRef<'_, '_> {
113 pub unsafe fn from_raw(raw: MlirRegion) -> Self {
119 Self {
120 raw,
121 _region: Default::default(),
122 }
123 }
124
125 pub unsafe fn from_option_raw(raw: MlirRegion) -> Option<Self> {
131 if raw.ptr.is_null() {
132 None
133 } else {
134 Some(Self::from_raw(raw))
135 }
136 }
137}
138
139impl<'c> Deref for RegionRef<'c, '_> {
140 type Target = Region<'c>;
141
142 fn deref(&self) -> &Self::Target {
143 unsafe { transmute(self) }
144 }
145}
146
147impl PartialEq for RegionRef<'_, '_> {
148 fn eq(&self, other: &Self) -> bool {
149 unsafe { mlirRegionEqual(self.raw, other.raw) }
150 }
151}
152
153impl Eq for RegionRef<'_, '_> {}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn new() {
161 Region::new();
162 }
163
164 #[test]
165 fn first_block() {
166 assert!(Region::new().first_block().is_none());
167 }
168
169 #[test]
170 fn append_block() {
171 let region = Region::new();
172 let block = Block::new(&[]);
173
174 region.append_block(block);
175
176 assert!(region.first_block().is_some());
177 }
178
179 #[test]
180 fn insert_block_after() {
181 let region = Region::new();
182
183 let block = region.append_block(Block::new(&[]));
184 region.insert_block_after(block, Block::new(&[]));
185
186 assert_eq!(region.first_block(), Some(block));
187 }
188
189 #[test]
190 fn insert_block_before() {
191 let region = Region::new();
192
193 let block = region.append_block(Block::new(&[]));
194 let block = region.insert_block_before(block, Block::new(&[]));
195
196 assert_eq!(region.first_block(), Some(block));
197 }
198
199 #[test]
200 fn equal() {
201 let region = Region::new();
202
203 assert_eq!(region, region);
204 }
205
206 #[test]
207 fn not_equal() {
208 assert_ne!(Region::new(), Region::new());
209 }
210}