1use crate::{
2 concurrent_slab::ConcurrentSlab,
3 language::parsed::{
4 AbiDeclaration, ConfigurableDeclaration, ConstGenericDeclaration, ConstantDeclaration,
5 EnumDeclaration, EnumVariant, FunctionDeclaration, ImplSelfOrTrait, StorageDeclaration,
6 StructDeclaration, TraitDeclaration, TraitFn, TraitTypeDeclaration, TypeAliasDeclaration,
7 VariableDeclaration,
8 },
9};
10
11use std::sync::Arc;
12use sway_types::{ProgramId, SourceId, Spanned};
13
14use super::parsed_id::ParsedDeclId;
15
16#[derive(Clone, Debug, Default)]
18pub struct ParsedDeclEngine {
19 variable_slab: ConcurrentSlab<VariableDeclaration>,
20 function_slab: ConcurrentSlab<FunctionDeclaration>,
21 trait_slab: ConcurrentSlab<TraitDeclaration>,
22 trait_fn_slab: ConcurrentSlab<TraitFn>,
23 trait_type_slab: ConcurrentSlab<TraitTypeDeclaration>,
24 impl_self_or_trait_slab: ConcurrentSlab<ImplSelfOrTrait>,
25 struct_slab: ConcurrentSlab<StructDeclaration>,
26 storage_slab: ConcurrentSlab<StorageDeclaration>,
27 abi_slab: ConcurrentSlab<AbiDeclaration>,
28 constant_slab: ConcurrentSlab<ConstantDeclaration>,
29 configurable_slab: ConcurrentSlab<ConfigurableDeclaration>,
30 const_generic_slab: ConcurrentSlab<ConstGenericDeclaration>,
31 enum_slab: ConcurrentSlab<EnumDeclaration>,
32 enum_variant_slab: ConcurrentSlab<EnumVariant>,
33 type_alias_slab: ConcurrentSlab<TypeAliasDeclaration>,
34}
35
36pub trait ParsedDeclEngineGet<I, U> {
37 fn get(&self, index: &I) -> Arc<U>;
38 fn map<R>(&self, index: &I, f: impl FnOnce(&U) -> R) -> R;
39}
40
41pub trait ParsedDeclEngineInsert<T> {
42 fn insert(&self, decl: T) -> ParsedDeclId<T>;
43}
44
45#[allow(unused)]
46pub trait ParsedDeclEngineReplace<T> {
47 fn replace(&self, index: ParsedDeclId<T>, decl: T);
48}
49
50#[allow(unused)]
51pub trait ParsedDeclEngineIndex<T>:
52 ParsedDeclEngineGet<ParsedDeclId<T>, T> + ParsedDeclEngineInsert<T> + ParsedDeclEngineReplace<T>
53{
54}
55
56macro_rules! decl_engine_get {
57 ($slab:ident, $decl:ty) => {
58 impl ParsedDeclEngineGet<ParsedDeclId<$decl>, $decl> for ParsedDeclEngine {
59 fn get(&self, index: &ParsedDeclId<$decl>) -> Arc<$decl> {
60 self.$slab.get(index.inner())
61 }
62
63 fn map<R>(&self, index: &ParsedDeclId<$decl>, f: impl FnOnce(&$decl) -> R) -> R {
64 self.$slab.map(index.inner(), f)
65 }
66 }
67 };
68}
69decl_engine_get!(variable_slab, VariableDeclaration);
70decl_engine_get!(function_slab, FunctionDeclaration);
71decl_engine_get!(trait_slab, TraitDeclaration);
72decl_engine_get!(trait_fn_slab, TraitFn);
73decl_engine_get!(trait_type_slab, TraitTypeDeclaration);
74decl_engine_get!(impl_self_or_trait_slab, ImplSelfOrTrait);
75decl_engine_get!(struct_slab, StructDeclaration);
76decl_engine_get!(storage_slab, StorageDeclaration);
77decl_engine_get!(abi_slab, AbiDeclaration);
78decl_engine_get!(constant_slab, ConstantDeclaration);
79decl_engine_get!(configurable_slab, ConfigurableDeclaration);
80decl_engine_get!(const_generic_slab, ConstGenericDeclaration);
81decl_engine_get!(enum_slab, EnumDeclaration);
82decl_engine_get!(enum_variant_slab, EnumVariant);
83decl_engine_get!(type_alias_slab, TypeAliasDeclaration);
84
85macro_rules! decl_engine_insert {
86 ($slab:ident, $decl:ty) => {
87 impl ParsedDeclEngineInsert<$decl> for ParsedDeclEngine {
88 fn insert(&self, decl: $decl) -> ParsedDeclId<$decl> {
89 ParsedDeclId::new(self.$slab.insert(decl))
90 }
91 }
92 };
93}
94
95decl_engine_insert!(variable_slab, VariableDeclaration);
96decl_engine_insert!(function_slab, FunctionDeclaration);
97decl_engine_insert!(trait_slab, TraitDeclaration);
98decl_engine_insert!(trait_fn_slab, TraitFn);
99decl_engine_insert!(trait_type_slab, TraitTypeDeclaration);
100decl_engine_insert!(impl_self_or_trait_slab, ImplSelfOrTrait);
101decl_engine_insert!(struct_slab, StructDeclaration);
102decl_engine_insert!(storage_slab, StorageDeclaration);
103decl_engine_insert!(abi_slab, AbiDeclaration);
104decl_engine_insert!(constant_slab, ConstantDeclaration);
105decl_engine_insert!(configurable_slab, ConfigurableDeclaration);
106decl_engine_insert!(const_generic_slab, ConstGenericDeclaration);
107decl_engine_insert!(enum_slab, EnumDeclaration);
108decl_engine_insert!(enum_variant_slab, EnumVariant);
109decl_engine_insert!(type_alias_slab, TypeAliasDeclaration);
110
111macro_rules! decl_engine_replace {
112 ($slab:ident, $decl:ty) => {
113 impl ParsedDeclEngineReplace<$decl> for ParsedDeclEngine {
114 fn replace(&self, index: ParsedDeclId<$decl>, decl: $decl) {
115 self.$slab.replace(index.inner(), decl);
116 }
117 }
118 };
119}
120
121decl_engine_replace!(variable_slab, VariableDeclaration);
122decl_engine_replace!(function_slab, FunctionDeclaration);
123decl_engine_replace!(trait_slab, TraitDeclaration);
124decl_engine_replace!(trait_fn_slab, TraitFn);
125decl_engine_replace!(trait_type_slab, TraitTypeDeclaration);
126decl_engine_replace!(impl_self_or_trait_slab, ImplSelfOrTrait);
127decl_engine_replace!(struct_slab, StructDeclaration);
128decl_engine_replace!(storage_slab, StorageDeclaration);
129decl_engine_replace!(abi_slab, AbiDeclaration);
130decl_engine_replace!(configurable_slab, ConfigurableDeclaration);
131decl_engine_replace!(constant_slab, ConstantDeclaration);
132decl_engine_replace!(enum_slab, EnumDeclaration);
133decl_engine_replace!(type_alias_slab, TypeAliasDeclaration);
134
135macro_rules! decl_engine_clear {
136 ($($slab:ident, $decl:ty);* $(;)?) => {
137 impl ParsedDeclEngine {
138 pub fn clear(&self) {
139 $(
140 self.$slab.clear();
141 )*
142 }
143 }
144 };
145}
146
147macro_rules! decl_engine_index {
148 ($slab:ident, $decl:ty) => {
149 impl ParsedDeclEngineIndex<$decl> for ParsedDeclEngine {}
150 };
151}
152decl_engine_index!(variable_slab, VariableDeclaration);
153decl_engine_index!(function_slab, FunctionDeclaration);
154decl_engine_index!(trait_slab, TraitDeclaration);
155decl_engine_index!(trait_fn_slab, TraitFn);
156decl_engine_index!(trait_type_slab, TraitTypeDeclaration);
157decl_engine_index!(impl_self_or_trait_slab, ImplSelfOrTrait);
158decl_engine_index!(struct_slab, StructDeclaration);
159decl_engine_index!(storage_slab, StorageDeclaration);
160decl_engine_index!(abi_slab, AbiDeclaration);
161decl_engine_index!(configurable_slab, ConfigurableDeclaration);
162decl_engine_index!(constant_slab, ConstantDeclaration);
163decl_engine_index!(enum_slab, EnumDeclaration);
164decl_engine_index!(type_alias_slab, TypeAliasDeclaration);
165
166decl_engine_clear!(
167 variable_slab, VariableDeclaration;
168 function_slab, FunctionDeclaration;
169 trait_slab, TraitDeclaration;
170 trait_fn_slab, TraitFn;
171 trait_type_slab, TraitTypeDeclaration;
172 impl_self_or_trait_slab, ImplTrait;
173 struct_slab, StructDeclaration;
174 storage_slab, StorageDeclaration;
175 abi_slab, AbiDeclaration;
176 constant_slab, ConstantDeclaration;
177 enum_slab, EnumDeclaration;
178 type_alias_slab, TypeAliasDeclaration;
179);
180
181macro_rules! decl_engine_clear_program {
182 ($(($slab:ident, $getter:expr)),* $(,)?) => {
183 impl ParsedDeclEngine {
184 pub fn clear_program(&mut self, program_id: &ProgramId) {
185 $(
186 self.$slab.retain(|_k, item| {
187 #[allow(clippy::redundant_closure_call)]
188 let span = $getter(item);
189 match span.source_id() {
190 Some(source_id) => &source_id.program_id() != program_id,
191 None => true,
192 }
193 });
194 )*
195 }
196 }
197 };
198}
199
200decl_engine_clear_program!(
201 (variable_slab, |item: &VariableDeclaration| item.name.span()),
202 (function_slab, |item: &FunctionDeclaration| item.name.span()),
203 (trait_slab, |item: &TraitDeclaration| item.name.span()),
204 (trait_fn_slab, |item: &TraitFn| item.name.span()),
205 (trait_type_slab, |item: &TraitTypeDeclaration| item
206 .name
207 .span()),
208 (impl_self_or_trait_slab, |item: &ImplSelfOrTrait| item
209 .block_span
210 .clone()),
211 (struct_slab, |item: &StructDeclaration| item.name.span()),
212 (storage_slab, |item: &StorageDeclaration| item.span.clone()),
213 (abi_slab, |item: &AbiDeclaration| item.name.span()),
214 (constant_slab, |item: &ConstantDeclaration| item.name.span()),
215 (enum_slab, |item: &EnumDeclaration| item.name.span()),
216 (type_alias_slab, |item: &TypeAliasDeclaration| item
217 .name
218 .span()),
219);
220
221macro_rules! decl_engine_clear_module {
222 ($(($slab:ident, $getter:expr)),* $(,)?) => {
223 impl ParsedDeclEngine {
224 pub fn clear_module(&mut self, program_id: &SourceId) {
225 $(
226 self.$slab.retain(|_k, item| {
227 #[allow(clippy::redundant_closure_call)]
228 let span = $getter(item);
229 match span.source_id() {
230 Some(src_id) => src_id != program_id,
231 None => true,
232 }
233 });
234 )*
235 }
236 }
237 };
238}
239
240decl_engine_clear_module!(
241 (variable_slab, |item: &VariableDeclaration| item.name.span()),
242 (function_slab, |item: &FunctionDeclaration| item.name.span()),
243 (trait_slab, |item: &TraitDeclaration| item.name.span()),
244 (trait_fn_slab, |item: &TraitFn| item.name.span()),
245 (trait_type_slab, |item: &TraitTypeDeclaration| item
246 .name
247 .span()),
248 (impl_self_or_trait_slab, |item: &ImplSelfOrTrait| item
249 .block_span
250 .clone()),
251 (struct_slab, |item: &StructDeclaration| item.name.span()),
252 (storage_slab, |item: &StorageDeclaration| item.span.clone()),
253 (abi_slab, |item: &AbiDeclaration| item.name.span()),
254 (constant_slab, |item: &ConstantDeclaration| item.name.span()),
255 (enum_slab, |item: &EnumDeclaration| item.name.span()),
256 (type_alias_slab, |item: &TypeAliasDeclaration| item
257 .name
258 .span()),
259);
260
261impl ParsedDeclEngine {
262 pub fn get_function<I>(&self, index: &I) -> Arc<FunctionDeclaration>
268 where
269 ParsedDeclEngine: ParsedDeclEngineGet<I, FunctionDeclaration>,
270 {
271 self.get(index)
272 }
273
274 pub fn get_trait<I>(&self, index: &I) -> Arc<TraitDeclaration>
280 where
281 ParsedDeclEngine: ParsedDeclEngineGet<I, TraitDeclaration>,
282 {
283 self.get(index)
284 }
285
286 pub fn get_trait_fn<I>(&self, index: &I) -> Arc<TraitFn>
292 where
293 ParsedDeclEngine: ParsedDeclEngineGet<I, TraitFn>,
294 {
295 self.get(index)
296 }
297
298 pub fn get_impl_self_or_trait<I>(&self, index: &I) -> Arc<ImplSelfOrTrait>
304 where
305 ParsedDeclEngine: ParsedDeclEngineGet<I, ImplSelfOrTrait>,
306 {
307 self.get(index)
308 }
309
310 pub fn get_struct<I>(&self, index: &I) -> Arc<StructDeclaration>
316 where
317 ParsedDeclEngine: ParsedDeclEngineGet<I, StructDeclaration>,
318 {
319 self.get(index)
320 }
321
322 pub fn get_storage<I>(&self, index: &I) -> Arc<StorageDeclaration>
328 where
329 ParsedDeclEngine: ParsedDeclEngineGet<I, StorageDeclaration>,
330 {
331 self.get(index)
332 }
333
334 pub fn get_abi<I>(&self, index: &I) -> Arc<AbiDeclaration>
340 where
341 ParsedDeclEngine: ParsedDeclEngineGet<I, AbiDeclaration>,
342 {
343 self.get(index)
344 }
345
346 pub fn get_constant<I>(&self, index: &I) -> Arc<ConstantDeclaration>
352 where
353 ParsedDeclEngine: ParsedDeclEngineGet<I, ConstantDeclaration>,
354 {
355 self.get(index)
356 }
357
358 pub fn get_configurable<I>(&self, index: &I) -> Arc<ConfigurableDeclaration>
364 where
365 ParsedDeclEngine: ParsedDeclEngineGet<I, ConfigurableDeclaration>,
366 {
367 self.get(index)
368 }
369
370 pub fn get_const_generic<I>(&self, index: &I) -> Arc<ConstGenericDeclaration>
376 where
377 ParsedDeclEngine: ParsedDeclEngineGet<I, ConstGenericDeclaration>,
378 {
379 self.get(index)
380 }
381
382 pub fn get_trait_type<I>(&self, index: &I) -> Arc<TraitTypeDeclaration>
388 where
389 ParsedDeclEngine: ParsedDeclEngineGet<I, TraitTypeDeclaration>,
390 {
391 self.get(index)
392 }
393
394 pub fn get_enum<I>(&self, index: &I) -> Arc<EnumDeclaration>
400 where
401 ParsedDeclEngine: ParsedDeclEngineGet<I, EnumDeclaration>,
402 {
403 self.get(index)
404 }
405
406 pub fn get_enum_variant<I>(&self, index: &I) -> Arc<EnumVariant>
412 where
413 ParsedDeclEngine: ParsedDeclEngineGet<I, EnumVariant>,
414 {
415 self.get(index)
416 }
417
418 pub fn get_type_alias<I>(&self, index: &I) -> Arc<TypeAliasDeclaration>
424 where
425 ParsedDeclEngine: ParsedDeclEngineGet<I, TypeAliasDeclaration>,
426 {
427 self.get(index)
428 }
429
430 pub fn get_variable<I>(&self, index: &I) -> Arc<VariableDeclaration>
436 where
437 ParsedDeclEngine: ParsedDeclEngineGet<I, VariableDeclaration>,
438 {
439 self.get(index)
440 }
441
442 pub fn pretty_print(&self) -> String {
443 use std::fmt::Write;
444 let mut s = String::new();
445 let _ = write!(
446 &mut s,
447 "Function Count: {}",
448 self.function_slab.values().len()
449 );
450 for f in self.function_slab.values() {
451 let _ = write!(&mut s, "Function: {}", f.name);
452 for node in f.body.contents.iter() {
453 let _ = write!(&mut s, " Node: {:#?}", node);
454 }
455 }
456
457 s
458 }
459}