sway_core/decl_engine/
parsed_engine.rs

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/// Used inside of type inference to store declarations.
17#[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}
39
40pub trait ParsedDeclEngineInsert<T> {
41    fn insert(&self, decl: T) -> ParsedDeclId<T>;
42}
43
44#[allow(unused)]
45pub trait ParsedDeclEngineReplace<T> {
46    fn replace(&self, index: ParsedDeclId<T>, decl: T);
47}
48
49#[allow(unused)]
50pub trait ParsedDeclEngineIndex<T>:
51    ParsedDeclEngineGet<ParsedDeclId<T>, T> + ParsedDeclEngineInsert<T> + ParsedDeclEngineReplace<T>
52{
53}
54
55macro_rules! decl_engine_get {
56    ($slab:ident, $decl:ty) => {
57        impl ParsedDeclEngineGet<ParsedDeclId<$decl>, $decl> for ParsedDeclEngine {
58            fn get(&self, index: &ParsedDeclId<$decl>) -> Arc<$decl> {
59                self.$slab.get(index.inner())
60            }
61        }
62    };
63}
64decl_engine_get!(variable_slab, VariableDeclaration);
65decl_engine_get!(function_slab, FunctionDeclaration);
66decl_engine_get!(trait_slab, TraitDeclaration);
67decl_engine_get!(trait_fn_slab, TraitFn);
68decl_engine_get!(trait_type_slab, TraitTypeDeclaration);
69decl_engine_get!(impl_self_or_trait_slab, ImplSelfOrTrait);
70decl_engine_get!(struct_slab, StructDeclaration);
71decl_engine_get!(storage_slab, StorageDeclaration);
72decl_engine_get!(abi_slab, AbiDeclaration);
73decl_engine_get!(constant_slab, ConstantDeclaration);
74decl_engine_get!(configurable_slab, ConfigurableDeclaration);
75decl_engine_get!(const_generic_slab, ConstGenericDeclaration);
76decl_engine_get!(enum_slab, EnumDeclaration);
77decl_engine_get!(enum_variant_slab, EnumVariant);
78decl_engine_get!(type_alias_slab, TypeAliasDeclaration);
79
80macro_rules! decl_engine_insert {
81    ($slab:ident, $decl:ty) => {
82        impl ParsedDeclEngineInsert<$decl> for ParsedDeclEngine {
83            fn insert(&self, decl: $decl) -> ParsedDeclId<$decl> {
84                ParsedDeclId::new(self.$slab.insert(decl))
85            }
86        }
87    };
88}
89
90decl_engine_insert!(variable_slab, VariableDeclaration);
91decl_engine_insert!(function_slab, FunctionDeclaration);
92decl_engine_insert!(trait_slab, TraitDeclaration);
93decl_engine_insert!(trait_fn_slab, TraitFn);
94decl_engine_insert!(trait_type_slab, TraitTypeDeclaration);
95decl_engine_insert!(impl_self_or_trait_slab, ImplSelfOrTrait);
96decl_engine_insert!(struct_slab, StructDeclaration);
97decl_engine_insert!(storage_slab, StorageDeclaration);
98decl_engine_insert!(abi_slab, AbiDeclaration);
99decl_engine_insert!(constant_slab, ConstantDeclaration);
100decl_engine_insert!(configurable_slab, ConfigurableDeclaration);
101decl_engine_insert!(const_generic_slab, ConstGenericDeclaration);
102decl_engine_insert!(enum_slab, EnumDeclaration);
103decl_engine_insert!(enum_variant_slab, EnumVariant);
104decl_engine_insert!(type_alias_slab, TypeAliasDeclaration);
105
106macro_rules! decl_engine_replace {
107    ($slab:ident, $decl:ty) => {
108        impl ParsedDeclEngineReplace<$decl> for ParsedDeclEngine {
109            fn replace(&self, index: ParsedDeclId<$decl>, decl: $decl) {
110                self.$slab.replace(index.inner(), decl);
111            }
112        }
113    };
114}
115
116decl_engine_replace!(variable_slab, VariableDeclaration);
117decl_engine_replace!(function_slab, FunctionDeclaration);
118decl_engine_replace!(trait_slab, TraitDeclaration);
119decl_engine_replace!(trait_fn_slab, TraitFn);
120decl_engine_replace!(trait_type_slab, TraitTypeDeclaration);
121decl_engine_replace!(impl_self_or_trait_slab, ImplSelfOrTrait);
122decl_engine_replace!(struct_slab, StructDeclaration);
123decl_engine_replace!(storage_slab, StorageDeclaration);
124decl_engine_replace!(abi_slab, AbiDeclaration);
125decl_engine_replace!(configurable_slab, ConfigurableDeclaration);
126decl_engine_replace!(constant_slab, ConstantDeclaration);
127decl_engine_replace!(enum_slab, EnumDeclaration);
128decl_engine_replace!(type_alias_slab, TypeAliasDeclaration);
129
130macro_rules! decl_engine_clear {
131    ($($slab:ident, $decl:ty);* $(;)?) => {
132        impl ParsedDeclEngine {
133            pub fn clear(&self) {
134                $(
135                    self.$slab.clear();
136                )*
137            }
138        }
139    };
140}
141
142macro_rules! decl_engine_index {
143    ($slab:ident, $decl:ty) => {
144        impl ParsedDeclEngineIndex<$decl> for ParsedDeclEngine {}
145    };
146}
147decl_engine_index!(variable_slab, VariableDeclaration);
148decl_engine_index!(function_slab, FunctionDeclaration);
149decl_engine_index!(trait_slab, TraitDeclaration);
150decl_engine_index!(trait_fn_slab, TraitFn);
151decl_engine_index!(trait_type_slab, TraitTypeDeclaration);
152decl_engine_index!(impl_self_or_trait_slab, ImplSelfOrTrait);
153decl_engine_index!(struct_slab, StructDeclaration);
154decl_engine_index!(storage_slab, StorageDeclaration);
155decl_engine_index!(abi_slab, AbiDeclaration);
156decl_engine_index!(configurable_slab, ConfigurableDeclaration);
157decl_engine_index!(constant_slab, ConstantDeclaration);
158decl_engine_index!(enum_slab, EnumDeclaration);
159decl_engine_index!(type_alias_slab, TypeAliasDeclaration);
160
161decl_engine_clear!(
162    variable_slab, VariableDeclaration;
163    function_slab, FunctionDeclaration;
164    trait_slab, TraitDeclaration;
165    trait_fn_slab, TraitFn;
166    trait_type_slab, TraitTypeDeclaration;
167    impl_self_or_trait_slab, ImplTrait;
168    struct_slab, StructDeclaration;
169    storage_slab, StorageDeclaration;
170    abi_slab, AbiDeclaration;
171    constant_slab, ConstantDeclaration;
172    enum_slab, EnumDeclaration;
173    type_alias_slab, TypeAliasDeclaration;
174);
175
176macro_rules! decl_engine_clear_program {
177    ($(($slab:ident, $getter:expr)),* $(,)?) => {
178        impl ParsedDeclEngine {
179            pub fn clear_program(&mut self, program_id: &ProgramId) {
180                $(
181                    self.$slab.retain(|_k, item| {
182                        #[allow(clippy::redundant_closure_call)]
183                        let span = $getter(item);
184                        match span.source_id() {
185                            Some(source_id) => &source_id.program_id() != program_id,
186                            None => true,
187                        }
188                    });
189                )*
190            }
191        }
192    };
193}
194
195decl_engine_clear_program!(
196    (variable_slab, |item: &VariableDeclaration| item.name.span()),
197    (function_slab, |item: &FunctionDeclaration| item.name.span()),
198    (trait_slab, |item: &TraitDeclaration| item.name.span()),
199    (trait_fn_slab, |item: &TraitFn| item.name.span()),
200    (trait_type_slab, |item: &TraitTypeDeclaration| item
201        .name
202        .span()),
203    (impl_self_or_trait_slab, |item: &ImplSelfOrTrait| item
204        .block_span
205        .clone()),
206    (struct_slab, |item: &StructDeclaration| item.name.span()),
207    (storage_slab, |item: &StorageDeclaration| item.span.clone()),
208    (abi_slab, |item: &AbiDeclaration| item.name.span()),
209    (constant_slab, |item: &ConstantDeclaration| item.name.span()),
210    (enum_slab, |item: &EnumDeclaration| item.name.span()),
211    (type_alias_slab, |item: &TypeAliasDeclaration| item
212        .name
213        .span()),
214);
215
216macro_rules! decl_engine_clear_module {
217    ($(($slab:ident, $getter:expr)),* $(,)?) => {
218        impl ParsedDeclEngine {
219            pub fn clear_module(&mut self, program_id: &SourceId) {
220                $(
221                    self.$slab.retain(|_k, item| {
222                        #[allow(clippy::redundant_closure_call)]
223                        let span = $getter(item);
224                        match span.source_id() {
225                            Some(src_id) => src_id != program_id,
226                            None => true,
227                        }
228                    });
229                )*
230            }
231        }
232    };
233}
234
235decl_engine_clear_module!(
236    (variable_slab, |item: &VariableDeclaration| item.name.span()),
237    (function_slab, |item: &FunctionDeclaration| item.name.span()),
238    (trait_slab, |item: &TraitDeclaration| item.name.span()),
239    (trait_fn_slab, |item: &TraitFn| item.name.span()),
240    (trait_type_slab, |item: &TraitTypeDeclaration| item
241        .name
242        .span()),
243    (impl_self_or_trait_slab, |item: &ImplSelfOrTrait| item
244        .block_span
245        .clone()),
246    (struct_slab, |item: &StructDeclaration| item.name.span()),
247    (storage_slab, |item: &StorageDeclaration| item.span.clone()),
248    (abi_slab, |item: &AbiDeclaration| item.name.span()),
249    (constant_slab, |item: &ConstantDeclaration| item.name.span()),
250    (enum_slab, |item: &EnumDeclaration| item.name.span()),
251    (type_alias_slab, |item: &TypeAliasDeclaration| item
252        .name
253        .span()),
254);
255
256impl ParsedDeclEngine {
257    /// Friendly helper method for calling the `get` method from the
258    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
259    ///
260    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
261    /// this method adds additional syntax that some users may find helpful.
262    pub fn get_function<I>(&self, index: &I) -> Arc<FunctionDeclaration>
263    where
264        ParsedDeclEngine: ParsedDeclEngineGet<I, FunctionDeclaration>,
265    {
266        self.get(index)
267    }
268
269    /// Friendly helper method for calling the `get` method from the
270    /// implementation of [DeclEngineGet] for [DeclEngine]
271    ///
272    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
273    /// this method adds additional syntax that some users may find helpful.
274    pub fn get_trait<I>(&self, index: &I) -> Arc<TraitDeclaration>
275    where
276        ParsedDeclEngine: ParsedDeclEngineGet<I, TraitDeclaration>,
277    {
278        self.get(index)
279    }
280
281    /// Friendly helper method for calling the `get` method from the
282    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
283    ///
284    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
285    /// this method adds additional syntax that some users may find helpful.
286    pub fn get_trait_fn<I>(&self, index: &I) -> Arc<TraitFn>
287    where
288        ParsedDeclEngine: ParsedDeclEngineGet<I, TraitFn>,
289    {
290        self.get(index)
291    }
292
293    /// Friendly helper method for calling the `get` method from the
294    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
295    ///
296    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
297    /// this method adds additional syntax that some users may find helpful.
298    pub fn get_impl_self_or_trait<I>(&self, index: &I) -> Arc<ImplSelfOrTrait>
299    where
300        ParsedDeclEngine: ParsedDeclEngineGet<I, ImplSelfOrTrait>,
301    {
302        self.get(index)
303    }
304
305    /// Friendly helper method for calling the `get` method from the
306    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
307    ///
308    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
309    /// this method adds additional syntax that some users may find helpful.
310    pub fn get_struct<I>(&self, index: &I) -> Arc<StructDeclaration>
311    where
312        ParsedDeclEngine: ParsedDeclEngineGet<I, StructDeclaration>,
313    {
314        self.get(index)
315    }
316
317    /// Friendly helper method for calling the `get` method from the
318    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine].
319    ///
320    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
321    /// this method adds additional syntax that some users may find helpful.
322    pub fn get_storage<I>(&self, index: &I) -> Arc<StorageDeclaration>
323    where
324        ParsedDeclEngine: ParsedDeclEngineGet<I, StorageDeclaration>,
325    {
326        self.get(index)
327    }
328
329    /// Friendly helper method for calling the `get` method from the
330    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
331    ///
332    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
333    /// this method adds additional syntax that some users may find helpful.
334    pub fn get_abi<I>(&self, index: &I) -> Arc<AbiDeclaration>
335    where
336        ParsedDeclEngine: ParsedDeclEngineGet<I, AbiDeclaration>,
337    {
338        self.get(index)
339    }
340
341    /// Friendly helper method for calling the `get` method from the
342    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
343    ///
344    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
345    /// this method adds additional syntax that some users may find helpful.
346    pub fn get_constant<I>(&self, index: &I) -> Arc<ConstantDeclaration>
347    where
348        ParsedDeclEngine: ParsedDeclEngineGet<I, ConstantDeclaration>,
349    {
350        self.get(index)
351    }
352
353    /// Friendly helper method for calling the `get` method from the
354    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
355    ///
356    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
357    /// this method adds additional syntax that some users may find helpful.
358    pub fn get_configurable<I>(&self, index: &I) -> Arc<ConfigurableDeclaration>
359    where
360        ParsedDeclEngine: ParsedDeclEngineGet<I, ConfigurableDeclaration>,
361    {
362        self.get(index)
363    }
364
365    /// Friendly helper method for calling the `get` method from the
366    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
367    ///
368    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
369    /// this method adds additional syntax that some users may find helpful.
370    pub fn get_const_generic<I>(&self, index: &I) -> Arc<ConstGenericDeclaration>
371    where
372        ParsedDeclEngine: ParsedDeclEngineGet<I, ConstGenericDeclaration>,
373    {
374        self.get(index)
375    }
376
377    /// Friendly helper method for calling the `get` method from the
378    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
379    ///
380    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
381    /// this method adds additional syntax that some users may find helpful.
382    pub fn get_trait_type<I>(&self, index: &I) -> Arc<TraitTypeDeclaration>
383    where
384        ParsedDeclEngine: ParsedDeclEngineGet<I, TraitTypeDeclaration>,
385    {
386        self.get(index)
387    }
388
389    /// Friendly helper method for calling the `get` method from the
390    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
391    ///
392    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
393    /// this method adds additional syntax that some users may find helpful.
394    pub fn get_enum<I>(&self, index: &I) -> Arc<EnumDeclaration>
395    where
396        ParsedDeclEngine: ParsedDeclEngineGet<I, EnumDeclaration>,
397    {
398        self.get(index)
399    }
400
401    /// Friendly helper method for calling the `get` method from the
402    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
403    ///
404    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
405    /// this method adds additional syntax that some users may find helpful.
406    pub fn get_enum_variant<I>(&self, index: &I) -> Arc<EnumVariant>
407    where
408        ParsedDeclEngine: ParsedDeclEngineGet<I, EnumVariant>,
409    {
410        self.get(index)
411    }
412
413    /// Friendly helper method for calling the `get` method from the
414    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
415    ///
416    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
417    /// this method adds additional syntax that some users may find helpful.
418    pub fn get_type_alias<I>(&self, index: &I) -> Arc<TypeAliasDeclaration>
419    where
420        ParsedDeclEngine: ParsedDeclEngineGet<I, TypeAliasDeclaration>,
421    {
422        self.get(index)
423    }
424
425    /// Friendly helper method for calling the `get` method from the
426    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
427    ///
428    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
429    /// this method adds additional syntax that some users may find helpful.
430    pub fn get_variable<I>(&self, index: &I) -> Arc<VariableDeclaration>
431    where
432        ParsedDeclEngine: ParsedDeclEngineGet<I, VariableDeclaration>,
433    {
434        self.get(index)
435    }
436
437    pub fn pretty_print(&self) -> String {
438        use std::fmt::Write;
439        let mut s = String::new();
440        let _ = write!(
441            &mut s,
442            "Function Count: {}",
443            self.function_slab.values().len()
444        );
445        for f in self.function_slab.values() {
446            let _ = write!(&mut s, "Function: {}", f.name);
447            for node in f.body.contents.iter() {
448                let _ = write!(&mut s, "    Node: {:#?}", node);
449            }
450        }
451
452        s
453    }
454}