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    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    /// Friendly helper method for calling the `get` method from the
263    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
264    ///
265    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
266    /// this method adds additional syntax that some users may find helpful.
267    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    /// Friendly helper method for calling the `get` method from the
275    /// implementation of [DeclEngineGet] for [DeclEngine]
276    ///
277    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
278    /// this method adds additional syntax that some users may find helpful.
279    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    /// Friendly helper method for calling the `get` method from the
287    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
288    ///
289    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
290    /// this method adds additional syntax that some users may find helpful.
291    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    /// Friendly helper method for calling the `get` method from the
299    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
300    ///
301    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
302    /// this method adds additional syntax that some users may find helpful.
303    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    /// Friendly helper method for calling the `get` method from the
311    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
312    ///
313    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
314    /// this method adds additional syntax that some users may find helpful.
315    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    /// Friendly helper method for calling the `get` method from the
323    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine].
324    ///
325    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
326    /// this method adds additional syntax that some users may find helpful.
327    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    /// Friendly helper method for calling the `get` method from the
335    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
336    ///
337    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
338    /// this method adds additional syntax that some users may find helpful.
339    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    /// Friendly helper method for calling the `get` method from the
347    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
348    ///
349    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
350    /// this method adds additional syntax that some users may find helpful.
351    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    /// Friendly helper method for calling the `get` method from the
359    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
360    ///
361    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
362    /// this method adds additional syntax that some users may find helpful.
363    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    /// Friendly helper method for calling the `get` method from the
371    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
372    ///
373    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
374    /// this method adds additional syntax that some users may find helpful.
375    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    /// Friendly helper method for calling the `get` method from the
383    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
384    ///
385    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
386    /// this method adds additional syntax that some users may find helpful.
387    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    /// Friendly helper method for calling the `get` method from the
395    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
396    ///
397    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
398    /// this method adds additional syntax that some users may find helpful.
399    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    /// Friendly helper method for calling the `get` method from the
407    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
408    ///
409    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
410    /// this method adds additional syntax that some users may find helpful.
411    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    /// Friendly helper method for calling the `get` method from the
419    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
420    ///
421    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
422    /// this method adds additional syntax that some users may find helpful.
423    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    /// Friendly helper method for calling the `get` method from the
431    /// implementation of [ParsedDeclEngineGet] for [ParsedDeclEngine]
432    ///
433    /// Calling [ParsedDeclEngine][get] directly is equivalent to this method, but
434    /// this method adds additional syntax that some users may find helpful.
435    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}