sway_core/semantic_analysis/
program.rs1use std::sync::Arc;
2
3use crate::{
4 language::{
5 parsed::ParseProgram,
6 ty::{self, TyModule, TyProgram},
7 },
8 metadata::MetadataManager,
9 semantic_analysis::{
10 namespace::{self, Root},
11 TypeCheckContext,
12 },
13 BuildConfig, Engines,
14};
15use sway_error::handler::{ErrorEmitted, Handler};
16use sway_features::ExperimentalFeatures;
17use sway_ir::{Context, Module};
18
19use super::{
20 symbol_collection_context::SymbolCollectionContext, TypeCheckAnalysis,
21 TypeCheckAnalysisContext, TypeCheckFinalization, TypeCheckFinalizationContext,
22};
23
24#[derive(Clone, Debug)]
25pub struct TypeCheckFailed {
26 pub root_module: Option<Arc<TyModule>>,
27 pub namespace: Root,
28 pub error: ErrorEmitted,
29}
30
31impl TyProgram {
32 pub fn collect(
37 handler: &Handler,
38 engines: &Engines,
39 parsed: &ParseProgram,
40 namespace: namespace::Namespace,
41 ) -> Result<SymbolCollectionContext, ErrorEmitted> {
42 let mut ctx = SymbolCollectionContext::new(namespace);
43 let ParseProgram { root, kind: _ } = parsed;
44
45 ty::TyModule::collect(handler, engines, &mut ctx, root)?;
46 Ok(ctx)
47 }
48
49 #[allow(clippy::too_many_arguments)]
54 pub fn type_check(
55 handler: &Handler,
56 engines: &Engines,
57 parsed: &ParseProgram,
58 collection_ctx: &mut SymbolCollectionContext,
59 mut namespace: namespace::Namespace,
60 package_name: &str,
61 build_config: Option<&BuildConfig>,
62 experimental: ExperimentalFeatures,
63 ) -> Result<Self, TypeCheckFailed> {
64 let mut ctx =
65 TypeCheckContext::from_root(&mut namespace, collection_ctx, engines, experimental)
66 .with_kind(parsed.kind);
67
68 let ParseProgram { root, kind } = parsed;
69
70 let root = ty::TyModule::type_check(
71 handler,
72 ctx.by_ref(),
73 engines,
74 parsed.kind,
75 root,
76 build_config,
77 )
78 .map_err(|error| TypeCheckFailed {
79 error,
80 root_module: None,
81 namespace: ctx.namespace.root_ref().clone(),
82 })?;
83
84 let (kind, declarations, configurables) = Self::validate_root(
85 handler,
86 engines,
87 &root,
88 *kind,
89 package_name,
90 ctx.experimental,
91 )
92 .map_err(|error| TypeCheckFailed {
93 error,
94 root_module: Some(root.clone()),
95 namespace: ctx.namespace.root_ref().clone(),
96 })?;
97
98 let program = TyProgram {
99 kind,
100 root_module: (*root).clone(),
101 namespace,
102 declarations,
103 configurables,
104 storage_slots: vec![],
105 logged_types: vec![],
106 messages_types: vec![],
107 };
108
109 Ok(program)
110 }
111
112 pub(crate) fn get_typed_program_with_initialized_storage_slots(
113 &mut self,
114 handler: &Handler,
115 engines: &Engines,
116 context: &mut Context,
117 md_mgr: &mut MetadataManager,
118 module: Module,
119 ) -> Result<(), ErrorEmitted> {
120 let decl_engine = engines.de();
121 match &self.kind {
122 ty::TyProgramKind::Contract { .. } => {
123 let storage_decl = self
124 .declarations
125 .iter()
126 .find(|decl| matches!(decl, ty::TyDecl::StorageDecl { .. }));
127
128 match storage_decl {
130 Some(ty::TyDecl::StorageDecl(ty::StorageDecl { decl_id, .. })) => {
131 let decl = decl_engine.get_storage(decl_id);
132 let mut storage_slots = decl.get_initialized_storage_slots(
133 handler, engines, context, md_mgr, module,
134 )?;
135 storage_slots.sort();
138 self.storage_slots = storage_slots;
139 Ok(())
140 }
141 _ => {
142 self.storage_slots = vec![];
143 Ok(())
144 }
145 }
146 }
147 _ => {
148 self.storage_slots = vec![];
149 Ok(())
150 }
151 }
152 }
153}
154
155impl TypeCheckAnalysis for TyProgram {
156 fn type_check_analyze(
157 &self,
158 handler: &Handler,
159 ctx: &mut TypeCheckAnalysisContext,
160 ) -> Result<(), ErrorEmitted> {
161 for node in self.root_module.all_nodes.iter() {
162 node.type_check_analyze(handler, ctx)?;
163 }
164 Ok(())
165 }
166}
167
168impl TypeCheckFinalization for TyProgram {
169 fn type_check_finalize(
170 &mut self,
171 handler: &Handler,
172 ctx: &mut TypeCheckFinalizationContext,
173 ) -> Result<(), ErrorEmitted> {
174 handler.scope(|handler| {
175 for node in self.root_module.all_nodes.iter_mut() {
176 let _ = node.type_check_finalize(handler, ctx);
177 }
178 Ok(())
179 })
180 }
181}