1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::{
    error::*,
    language::{parsed::ParseProgram, ty},
    metadata::MetadataManager,
    semantic_analysis::{
        namespace::{self, Namespace},
        TypeCheckContext,
    },
    Engines,
};
use sway_ir::{Context, Module};

impl ty::TyProgram {
    /// Type-check the given parsed program to produce a typed program.
    ///
    /// The given `initial_namespace` acts as an initial state for each module within this program.
    /// It should contain a submodule for each library package dependency.
    pub fn type_check(
        engines: Engines<'_>,
        parsed: &ParseProgram,
        initial_namespace: namespace::Module,
    ) -> CompileResult<Self> {
        let mut namespace = Namespace::init_root(initial_namespace);
        let ctx =
            TypeCheckContext::from_root(&mut namespace, engines).with_kind(parsed.kind.clone());
        let ParseProgram { root, kind } = parsed;
        let mod_span = root.tree.span.clone();
        let mod_res = ty::TyModule::type_check(ctx, root);
        mod_res.flat_map(|root| {
            let res = Self::validate_root(engines, &root, kind.clone(), mod_span);
            res.map(|(kind, declarations, configurables)| Self {
                kind,
                root,
                declarations,
                configurables,
                storage_slots: vec![],
                logged_types: vec![],
                messages_types: vec![],
            })
        })
    }

    pub(crate) fn get_typed_program_with_initialized_storage_slots(
        self,
        engines: Engines<'_>,
        context: &mut Context,
        md_mgr: &mut MetadataManager,
        module: Module,
    ) -> CompileResult<Self> {
        let mut warnings = vec![];
        let mut errors = vec![];
        let decl_engine = engines.de();
        match &self.kind {
            ty::TyProgramKind::Contract { .. } => {
                let storage_decl = self
                    .declarations
                    .iter()
                    .find(|decl| matches!(decl, ty::TyDeclaration::StorageDeclaration { .. }));

                // Expecting at most a single storage declaration
                match storage_decl {
                    Some(ty::TyDeclaration::StorageDeclaration {
                        decl_id, decl_span, ..
                    }) => {
                        let decl = check!(
                            CompileResult::from(decl_engine.get_storage(decl_id, decl_span)),
                            return err(warnings, errors),
                            warnings,
                            errors
                        );
                        let mut storage_slots = check!(
                            decl.get_initialized_storage_slots(engines, context, md_mgr, module),
                            return err(warnings, errors),
                            warnings,
                            errors,
                        );
                        // Sort the slots to standardize the output. Not strictly required by the
                        // spec.
                        storage_slots.sort();
                        ok(
                            Self {
                                storage_slots,
                                ..self
                            },
                            warnings,
                            errors,
                        )
                    }
                    _ => ok(
                        Self {
                            storage_slots: vec![],
                            ..self
                        },
                        warnings,
                        errors,
                    ),
                }
            }
            _ => ok(
                Self {
                    storage_slots: vec![],
                    ..self
                },
                warnings,
                errors,
            ),
        }
    }
}