Skip to main content

cubecl_core/frontend/container/registry/
base.rs

1use alloc::{collections::BTreeMap, rc::Rc};
2use core::cell::RefCell;
3
4use cubecl_ir::Scope;
5
6use crate::prelude::*;
7
8/// It is similar to a map, but where the keys are stored at comptime, but the values can be runtime
9/// variables.
10pub struct Registry<K, V> {
11    map: Rc<RefCell<BTreeMap<K, V>>>,
12}
13
14/// To [find](Registry::find) an item from the [registry](Registry), the query must
15/// be able to be translated to the actual key type.
16///
17/// # Example
18///
19/// If you use [u32] as key that may become [`crate::frontend::NativeExpand<u32>`] during the expansion, both types
20/// need to implement [`RegistryQuery`].
21pub trait RegistryQuery<K>: Into<K> {}
22
23// We provide default implementations for some types.
24impl RegistryQuery<u32> for u32 {}
25impl RegistryQuery<usize> for usize {}
26
27impl<K: PartialOrd + Ord + core::fmt::Debug, V: CubeType<ExpandType: Clone> + Clone>
28    Registry<K, V>
29{
30    /// Create a new registry.
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    /// Expand function of [`Self::new`].
36    pub fn __expand_new(_: &Scope) -> Registry<K, V::ExpandType> {
37        Registry {
38            map: Rc::new(RefCell::new(BTreeMap::new())),
39        }
40    }
41
42    /// Find an item in the registry.
43    ///
44    /// # Notes
45    ///
46    /// If the item isn't present in the registry, the function will panic.
47    pub fn find<Query: RegistryQuery<K>>(&self, query: Query) -> V {
48        let key = query.into();
49        let map = self.map.as_ref().borrow();
50
51        match map.get(&key) {
52            Some(val) => val.clone(),
53            None => panic!("No value found for key {key:?}"),
54        }
55    }
56
57    /// Find an item in the registry or return the default value.
58    pub fn find_or_default<Query: RegistryQuery<K>>(&mut self, query: Query) -> V
59    where
60        V: Default,
61        K: Clone,
62    {
63        let key = query.into();
64        let mut map = self.map.as_ref().borrow_mut();
65
66        match map.get(&key) {
67            Some(val) => val.clone(),
68            None => {
69                map.insert(key.clone(), Default::default());
70                map.get(&key).unwrap().clone()
71            }
72        }
73    }
74
75    /// Insert an item in the registry.
76    pub fn insert<Query: RegistryQuery<K>>(&mut self, query: Query, value: V) {
77        let key = query.into();
78        let mut map = self.map.as_ref().borrow_mut();
79
80        map.insert(key, value);
81    }
82
83    /// Expand function of [`Self::find`].
84    pub fn __expand_find<Query: RegistryQuery<K>>(
85        _scope: &Scope,
86        state: Registry<K, V::ExpandType>,
87        key: Query,
88    ) -> V::ExpandType {
89        let key = key.into();
90        let map = state.map.as_ref().borrow();
91
92        map.get(&key).unwrap().clone()
93    }
94
95    /// Expand function of [`Self::find_or_default`].
96    pub fn __expand_find_or_default<Query: RegistryQuery<K>>(
97        _scope: &Scope,
98        state: &mut Registry<K, V::ExpandType>,
99        key: Query,
100    ) -> V::ExpandType
101    where
102        V::ExpandType: Default,
103        K: Clone,
104    {
105        let key = key.into();
106        let mut map = state.map.as_ref().borrow_mut();
107
108        match map.get(&key) {
109            Some(val) => val.clone(),
110            None => {
111                map.insert(key.clone(), Default::default());
112                map.get(&key).unwrap().clone()
113            }
114        }
115    }
116
117    /// Expand function of [`Self::insert`].
118    pub fn __expand_insert<Key: Into<K>>(
119        _scope: &Scope,
120        state: &mut Registry<K, V::ExpandType>,
121        key: Key,
122        value: V::ExpandType,
123    ) {
124        let key = key.into();
125        let mut map = state.map.as_ref().borrow_mut();
126
127        map.insert(key, value);
128    }
129}
130
131impl<K: PartialOrd + Ord + core::fmt::Debug, V: Clone> Registry<K, V> {
132    /// Expand method of [`Self::find`].
133    pub fn __expand_find_method(&self, _scope: &Scope, key: K) -> V {
134        let map = self.map.as_ref().borrow();
135
136        match map.get(&key) {
137            Some(val) => val.clone(),
138            None => panic!("No value found for key {key:?}"),
139        }
140    }
141
142    /// Expand method of [`Self::insert`].
143    pub fn __expand_insert_method(&mut self, _scope: &Scope, key: K, value: V) {
144        let mut map = self.map.as_ref().borrow_mut();
145
146        map.insert(key, value);
147    }
148}
149
150impl<K, V> Default for Registry<K, V> {
151    fn default() -> Self {
152        Self {
153            map: Rc::new(RefCell::new(BTreeMap::default())),
154        }
155    }
156}
157
158impl<K, V> Clone for Registry<K, V> {
159    fn clone(&self) -> Self {
160        Self {
161            map: self.map.clone(),
162        }
163    }
164}
165impl<K, V> ExpandTypeClone for Registry<K, V> {
166    fn clone_unchecked(&self) -> Self {
167        self.clone()
168    }
169}
170
171impl<K, V> IntoExpand for Registry<K, V> {
172    type Expand = Self;
173
174    fn into_expand(self, _scope: &Scope) -> Self::Expand {
175        self
176    }
177}
178
179impl<K: PartialOrd + Ord, V: CubeType<ExpandType: Clone>> CubeType for Registry<K, V> {
180    type ExpandType = Registry<K, V::ExpandType>;
181}
182
183impl<K: PartialOrd + Ord, V: IntoMut + Clone> IntoMut for Registry<K, V> {
184    fn into_mut(self, scope: &Scope) -> Self {
185        let mut map = self.map.borrow_mut();
186        map.iter_mut().for_each(|(_k, v)| {
187            *v = IntoMut::into_mut(v.clone(), scope);
188        });
189        core::mem::drop(map);
190
191        self
192    }
193}
194
195impl<K: PartialOrd + Ord, V> CubeDebug for Registry<K, V> {}
196
197impl<K, V> AsRefExpand for Registry<K, V> {
198    fn __expand_ref_method(&self, _: &Scope) -> &Self {
199        self
200    }
201}
202impl<K, V> AsMutExpand for Registry<K, V> {
203    fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
204        self
205    }
206}