open_vaf/ir/
ids.rs

1//  * ******************************************************************************************
2//  * Copyright (c) 2019 Pascal Kuthe. This file is part of the OpenVAF project.
3//  * It is subject to the license terms in the LICENSE file found in the top-level directory
4//  *  of this distribution and at  https://gitlab.com/DSPOM/OpenVAF/blob/master/LICENSE.
5//  *  No part of OpenVAF, including this file, may be copied, modified, propagated, or
6//  *  distributed except according to the terms contained in the LICENSE file.
7//  * *******************************************************************************************
8
9//! All IRS use preallocated Arenas for each node type. These Ids and their implementations are generated using the `id_type!` macro in this module.
10//! The [`impl_id_type!`](impl_id_type) is also defined here which provides the implementation necessary for an ID type to interact with an IR
11
12// IndexVec macro is a bit unpretty atm
13#![allow(clippy::doc_markdown)]
14#![allow(clippy::used_underscore_binding)]
15
16use std::fmt::Debug;
17use std::ops::Range;
18use index_vec::Idx;
19use more_asserts::assert_gt;
20use pretty_assertions::assert_eq;
21use std::iter;
22
23
24pub type IdxRangeIter<I> = iter::Map<Range<usize>, fn(usize) -> I>;
25
26macro_rules! id_type {
27    ($name:ident($type:ident)) => {
28        // see the index_vec documentation
29        ::index_vec::define_index_type! {
30            pub struct $name = $type;
31
32            DISPLAY_FORMAT = "{}";
33
34            DEBUG_FORMAT = stringify!(<$name {}>);
35
36            IMPL_RAW_CONVERSIONS = true;
37        }
38    };
39}
40
41id_type!(BranchId(u16));
42
43id_type!(NetId(u16));
44
45id_type!(PortId(u16));
46
47id_type!(ParameterId(u32));
48
49id_type!(VariableId(u32));
50
51id_type!(ModuleId(u16));
52
53id_type!(FunctionId(u16));
54
55id_type!(DisciplineId(u16));
56
57id_type!(ExpressionId(u32));
58id_type!(RealExpressionId(u32));
59id_type!(IntegerExpressionId(u32));
60id_type!(StringExpressionId(u32));
61
62id_type!(BlockId(u16));
63
64id_type!(AttributeId(u16));
65
66id_type!(StatementId(u32));
67
68id_type!(NatureId(u16));
69
70#[derive(Clone, Debug)]
71pub struct IdRange<I: Idx>(pub Range<I>);
72
73impl<I: Idx> IdRange<I> {
74    pub fn enter_back(&mut self, sub_range: &Self) -> Self {
75        if cfg!(debug_assertions) && self.len() != 0 {
76            assert_eq!(self.0.end, sub_range.0.end);
77            assert_gt!(sub_range.0.start, self.0.start);
78        }
79
80        self.0.end = sub_range.0.start;
81
82        sub_range.clone()
83    }
84}
85
86impl<I: Idx> Iterator for IdRange<I> {
87    type Item = I;
88
89    #[inline]
90    fn next(&mut self) -> Option<Self::Item> {
91        if self.0.start < self.0.end {
92            let res = self.0.start;
93            self.0.start = I::from_usize(self.0.start.index() + 1);
94            Some(res)
95        } else {
96            None
97        }
98    }
99
100    #[inline]
101    fn size_hint(&self) -> (usize, Option<usize>) {
102        let len = self.len();
103        (len, Some(len))
104    }
105
106    #[inline]
107    fn count(self) -> usize {
108        self.len()
109    }
110
111    #[inline]
112    fn last(mut self) -> Option<Self::Item> {
113        self.next_back()
114    }
115
116    #[inline]
117    fn max(self) -> Option<Self::Item> {
118        self.last()
119    }
120
121    #[inline]
122    fn min(self) -> Option<Self::Item> {
123        Some(self.0.start)
124    }
125
126    fn nth(&mut self, n: usize) -> Option<Self::Item> {
127        let new_start = I::from_usize(self.0.start.index() + n);
128        if new_start < self.0.end {
129            self.0.start = I::from_usize(new_start.index() + 1);
130            Some(new_start)
131        } else {
132            self.0.start = self.0.end;
133            None
134        }
135    }
136}
137
138impl<I: Idx> ExactSizeIterator for IdRange<I> {
139    fn len(&self) -> usize {
140        self.0.end.index() - self.0.start.index()
141    }
142}
143
144impl<I: Idx> DoubleEndedIterator for IdRange<I> {
145    fn next_back(&mut self) -> Option<Self::Item> {
146        if self.0.start < self.0.end {
147            self.0.end = I::from_usize(self.0.end.index() - 1);
148            Some(self.0.end)
149        } else {
150            None
151        }
152    }
153
154    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
155        let new_end = I::from_usize(self.0.end.index() - n);
156        if self.0.start < new_end {
157            self.0.end = I::from_usize(new_end.index() - 1);
158            Some(new_end)
159        } else {
160            self.0.end = self.0.start;
161            None
162        }
163    }
164}
165
166/// Provides the implementation which allows the data of an IR to be accessed using an ID type generated using the `id_type!` macro.
167///
168///
169/// # Arguments
170///
171/// * `$name` - the identifier of the id type
172///
173/// * `$container` - the identifier of the IR
174///
175/// * `$sub_container` - the field of the ir which contains the [Arena](crate::compact_arena) this ID indexes
176///
177/// * `$type` - The type of the values that are indexed by this id
178///
179/// # Examples
180///
181/// ```
182/// id_type!(NetId(u8));
183/// impl_id_type!(NetId in Ast::nets -> AttributeNode<Net>);
184/// ```
185
186#[macro_export]
187macro_rules! impl_id_type {
188    ($name:ident in $container:ident::$sub_container:ident -> $type:ty) => {
189        impl ::std::ops::Index<$name> for $container {
190            type Output = $type;
191            fn index(&self, index: $name) -> &Self::Output {
192                &self.$sub_container[index]
193            }
194        }
195
196        impl ::std::ops::IndexMut<$name> for $container {
197            fn index_mut(&mut self, index: $name) -> &mut Self::Output {
198                &mut self.$sub_container[index]
199            }
200        }
201
202        impl ::std::ops::Index<Range<$name>> for $container {
203            type Output = ::index_vec::IndexSlice<$name, [$type]>;
204            fn index(&self, range: Range<$name>) -> &Self::Output {
205                &self.$sub_container[range]
206            }
207        }
208
209        impl ::std::ops::IndexMut<Range<$name>> for $container {
210            fn index_mut(&mut self, range: Range<$name>) -> &mut Self::Output {
211                &mut self.$sub_container[range]
212            }
213        }
214
215        impl ::std::ops::Index<$crate::ir::ids::IdRange<$name>> for $container {
216            type Output = ::index_vec::IndexSlice<$name, [$type]>;
217            fn index(&self, range: $crate::ir::ids::IdRange<$name>) -> &Self::Output {
218                &self.$sub_container[range.0]
219            }
220        }
221
222        impl ::std::ops::IndexMut<$crate::ir::ids::IdRange<$name>> for $container {
223            fn index_mut(&mut self, range: $crate::ir::ids::IdRange<$name>) -> &mut Self::Output {
224                &mut self.$sub_container[range.0]
225            }
226        }
227    };
228}