sway_core/semantic_analysis/
program.rs1use std::sync::Arc;
2
3use super::symbol_collection_context::SymbolCollectionContext;
4use crate::{
5 language::{
6 parsed::ParseProgram,
7 ty::{self, TyModule, TyProgram},
8 },
9 metadata::MetadataManager,
10 semantic_analysis::{
11 namespace::{self, Package},
12 TypeCheckContext,
13 },
14 BuildConfig, Engines,
15};
16use sway_error::handler::{ErrorEmitted, Handler};
17use sway_ir::{Context, Module};
18
19#[derive(Clone, Debug)]
20pub struct TypeCheckFailed {
21 pub root_module: Option<Arc<TyModule>>,
22 pub namespace: Package,
23 pub error: ErrorEmitted,
24}
25
26impl TyProgram {
27 pub fn collect(
32 handler: &Handler,
33 engines: &Engines,
34 parsed: &ParseProgram,
35 namespace: namespace::Namespace,
36 ) -> Result<SymbolCollectionContext, ErrorEmitted> {
37 let mut ctx = SymbolCollectionContext::new(namespace);
38 let ParseProgram { root, kind: _ } = parsed;
39
40 ty::TyModule::collect(handler, engines, &mut ctx, root)?;
41 Ok(ctx)
42 }
43
44 #[allow(clippy::result_large_err)]
49 #[allow(clippy::too_many_arguments)]
50 pub fn type_check(
51 handler: &Handler,
52 engines: &Engines,
53 parsed: &ParseProgram,
54 package_name: &str,
55 build_config: Option<&BuildConfig>,
56 ctx: &mut TypeCheckContext,
57 ) -> Result<Self, TypeCheckFailed> {
58 let ParseProgram { root, kind } = parsed;
59
60 let root = ty::TyModule::type_check(
61 handler,
62 ctx.by_ref(),
63 engines,
64 parsed.kind,
65 root,
66 build_config,
67 )
68 .map_err(|error| TypeCheckFailed {
69 error,
70 root_module: None,
71 namespace: ctx.namespace.current_package_ref().clone(),
72 })?;
73
74 let experimental = ctx.experimental;
75 let (kind, declarations, configurables) =
76 Self::validate_root(handler, engines, &root, *kind, package_name, experimental)
77 .map_err(|error| TypeCheckFailed {
78 error,
79 root_module: Some(root.clone()),
80 namespace: ctx.namespace.current_package_ref().clone(),
81 })?;
82
83 let mut namespace = ctx.namespace().clone();
84 Self::validate_coherence(handler, engines, &root, &mut namespace).map_err(|error| {
85 TypeCheckFailed {
86 error,
87 root_module: Some(root.clone()),
88 namespace: ctx.namespace.current_package_ref().clone(),
89 }
90 })?;
91
92 let program = TyProgram {
93 kind,
94 root_module: (*root).clone(),
95 namespace,
96 declarations,
97 configurables,
98 storage_slots: vec![],
99 logged_types: vec![],
100 messages_types: vec![],
101 };
102
103 Ok(program)
104 }
105
106 pub(crate) fn get_typed_program_with_initialized_storage_slots(
107 &mut self,
108 handler: &Handler,
109 engines: &Engines,
110 context: &mut Context,
111 md_mgr: &mut MetadataManager,
112 module: Module,
113 ) -> Result<(), ErrorEmitted> {
114 let decl_engine = engines.de();
115 match &self.kind {
116 ty::TyProgramKind::Contract { .. } => {
117 let storage_decl = self
118 .declarations
119 .iter()
120 .find(|decl| matches!(decl, ty::TyDecl::StorageDecl { .. }));
121
122 match storage_decl {
124 Some(ty::TyDecl::StorageDecl(ty::StorageDecl { decl_id, .. })) => {
125 let decl = decl_engine.get_storage(decl_id);
126 let mut storage_slots = decl.get_initialized_storage_slots(
127 handler, engines, context, md_mgr, module,
128 )?;
129 storage_slots.sort();
132 self.storage_slots = storage_slots;
133 Ok(())
134 }
135 _ => {
136 self.storage_slots = vec![];
137 Ok(())
138 }
139 }
140 }
141 _ => {
142 self.storage_slots = vec![];
143 Ok(())
144 }
145 }
146 }
147}